簡體   English   中英

在Go中解析JSON

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM