[英]Parsing JSON in go
我的問題是關於在golang中解析JSON文件。
具體來說,我正在嘗試解析命令“ docker network inspect bridge”的輸出,該輸出恰好是JSON格式。 該命令在此處描述。 我的目標是獲取列出容器的“ IPv4Address”列表。
我嘗試這樣做,但是無法將map [string] interface {}轉換為map [string] string。 我的代碼在這里: -https : //play.golang.org/p/eO_j996gGb
$ sudo docker network inspect bridge
[
{
"Name": "bridge",
"Id": "b2b1a2cba717161d984383fd68218cf70bbbd17d328496885f7c921333228b0f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.42.1/16",
"Gateway": "172.17.42.1"
}
]
},
"Internal": false,
"Containers": {
"bda12f8922785d1f160be70736f26c1e331ab8aaf8ed8d56728508f2e2fd4727": {
"Name": "container2",
"EndpointID": "0aebb8fcd2b282abe1365979536f21ee4ceaf3ed56177c628eae9f706e00e019",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"f2870c98fd504370fb86e59f32cd0753b1ac9b69b7d80566ffc7192a82b3ed27": {
"Name": "container1",
"EndpointID": "a00676d9c91a96bbe5bcfb34f705387a33d7cc365bac1a29e4e9728df92d10ad",
"MacAddress": "02:42:ac:11:00:01",
"IPv4Address": "172.17.0.1/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
在golang中解析此類JSON文件的正確方法是什么? 我確實嘗試過使用類型轉換,但沒有幫助。 我嘗試了很多事情,但最終只能達到代碼片段中顯示的代碼。 如何從“續”對象中提取IPv4Address字段?
我擁有的去游樂場的鏈接是https://play.golang.org/p/eO_j996gGb 。 非常感謝您提供的任何幫助(願意嘗試一下,不需要代碼,但有想法:)謝謝。
您只需修改您的代碼以進一步解包數據。 您留下的每個容器對象都以interface{}
表示,這使得它無法訪問其中的字段。 每個聲明的另一個聲明使其成為map[string]interface{}
將允許您按名稱訪問字段(例如IPv4Address
)。 這是一個可行的例子; https://play.golang.org/p/4OC5axN4Gd
這是重要的代碼更改;
containers := (foo[0]["Containers"]).(map[string]interface{})
//fmt.Printf("containers %+v", containers)
for _, v := range containers {
unwrapped := v.(map[string]interface{})
fmt.Printf("\ncont %+v\n", unwrapped["IPv4Address"])
}
v
只是一個interface{}
因此如果不重新聲明/轉換為類型,就無法訪問IPv4Address
字段。
但是,現在一切正常,我建議您避免大量使用代碼中的接口。 您的代碼中充滿了不安全的操作,這些操作會產生大量的錯誤處理需求(例如,每次嘗試訪問映射時,您都有可能引發該錯誤,以及每次執行類型斷言時)。 有很多關於如何在SO上執行此操作的示例,但是如果您提出評論要求,我可以提供另一個可以解編為結構的示例。 這是更安全和可維護的imo,因為大多數錯誤將在調用元帥的過程中引發,而不是擁有大量可能導致結果恐慌的代碼,而這些代碼可能無法正常工作。
這是一些播放代碼,其中包含所有類型,並且使用unmarshal; https://play.golang.org/p/VfHst9GaiR
您的類型可以用以下表示;
type DockerInstance struct {
Name string `json:"Name"`
Id string `json:"Id"`
Scope string `json:"Scope"`
Driver string `json:"Driver"`
EnableIPv6 bool `json:"EnableIPv6"`
IPAM IPAM `json:"IPAM"`
Internal bool `json:"Internal"`
Containers map[string]Container `json:"Containers"`
Options map[string]string `json:"Options"`
Labels interface{} `json:"Labels"`
}
type IPAM struct {
Driver string `json:"Driver"`
Options interface{} `json:"Options"`
Config []Conf `json:"Config"`
}
type Conf struct {
Subnet string `json:"Subnet"`
}
type Container struct {
Name string `json:"Name"`
EndPointID string `json:"EndpointID"`
MacAddress string `json:"MacAddress"`
IPv4Address string `json:"IPv4Address"`
IPv6Address string `json:"IPv6Address"`
}
我仍然需要設置一些接口,這只是因為示例json不包含任何數據,所以我不知道Go源代碼中的類型。 我還在您的主程序中添加了一些基本內容,以測試對象/確保正確定義了內容;
docks := []DockerInstance{} //note you're using an array of the top level type
err := json.Unmarshal([]byte(teststring), &docks)
if err != nil {
fmt.Println(err)
} else {
fmt.Println()
fmt.Println()
fmt.Println(docks[0].Name)
}
for k, v := range docks[0].Containers {
fmt.Println(k)
fmt.Println(v.IPv4Address)
}
for k, v := range docks[0].Options {
fmt.Println(k)
fmt.Println(v)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.