2016-10-03 17 views
0

Meine Frage geht über die Analyse von JSON-Dateien in Golang.Parsen von JSON in go

Genauer gesagt, ich versuche, die Ausgabe eines Befehls "Docker Netzwerk inspect Brücke" zu analysieren, die im JSON-Format ist. Der Befehl wird hier beschrieben. Mein Ziel ist es, eine Liste von "IPv4Address" für die aufgelisteten Container zu bekommen.

Ich habe versucht, dies zu tun, aber nicht zu konvertieren map [string] Schnittstelle {} zu Karte [string] string. Mein Code ist hier: - 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" 
     } 
    } 
] 

Was ist der richtige Weg solche JSON-Dateien in golang zu analysieren. Ich habe versucht, die Typkonvertierung zu verwenden, aber das hilft nicht. Ich habe viele Dinge ausprobiert, aber letztendlich konnte ich nur so weit kommen wie der Code, der im Snippet gezeigt wird. Wie kann ich das Feld IPv4Address aus dem Objekt "cont" extrahieren?

Link zum Spielplatz Snippet Ich habe ist https://play.golang.org/p/eO_j996gGb. Jede Hilfe wird sehr geschätzt (bereit, Dinge auszuprobieren, nicht nur den Code, sondern Ideen :) Danke.

+0

Noch ein Hinweis: Die meisten Docker-Befehle akzeptieren eine '--format'-Option, die eine Golang-Vorlage (aus dem' text/template') -Paket sein muss. – TheHippo

Antwort

2

Ihr Code muss nur modifiziert werden, um die Daten weiter zu entpacken. Sie verlassen es mit jedem Containerobjekt, das als interface{} dargestellt wird, wodurch Sie nicht auf die Felder zugreifen können. Eine andere Behauptung auf jeder, um es zu einem map[string]interface{} zu machen erlaubt Ihnen, auf die Felder innerhalb durch Namen (wie IPv4Address) zuzugreifen. Hier ist ein funktionierendes Beispiel; https://play.golang.org/p/4OC5axN4Gd

Hier ist die wichtige Codeänderung;

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 ist nur ein interface{} so haben Sie keine Möglichkeit, die IPv4Address Feld zuzugreifen, ohne wieder zu behaupten/in einen Typ umgewandelt wird.

Nun, das funktioniert gut, aber ich würde empfehlen, weg von der starken Verwendung von Schnittstellen in Ihrem Code. Ihr Code ist voll von unsicheren Operationen, die eine Menge an Fehlerbehandlung erfordern (wie jedes Mal, wenn Sie versuchen, auf die Karte zuzugreifen, die Sie werfen können, sowie jederzeit, wenn Sie eine Typ-Assertion durchführen). Es gibt viele Beispiele dafür, wie man das hier auf SO macht, aber wenn Sie einen Kommentar hinterlassen, der es anfordert, kann ich ein weiteres Beispiel erzeugen, das in Strukturen entpackt wird. Dies ist viel sicherer und wartbar imo, weil die meisten Fehler auf den Aufruf zu unmarshal, statt potenziell viel Code, der mit den Ergebnissen, die alle eine Panik verursachen könnte, haben wird ausgelöst werden.

Hier ist ein Spielcode, der alle Typen enthält und unmarshal verwendet; https://play.golang.org/p/VfHst9GaiR

Ihre Typen können wie folgt dargestellt werden;

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"` 
} 

ist es ein paar Sachen, die ich gesetzt habe noch eine Schnittstelle, das ist verursacht nur die Probe json enthält keine Daten für sie, so kann ich nicht wissen, was ihre Art in der Go Quelle sein sollte. Hier sind ein paar grundlegende Dinge, die ich auch in deinem main hinzugefügt habe, um die Objekte zu testen/stelle sicher, dass ich die Dinge richtig definiert habe;

+0

Vielen Dank. Ich bin dem Code sehr nahe gekommen, als du gestern die Dinge ausprobiert hast, aber manchmal funktionieren die Dinge einfach nicht :(. Ja, ich bin an der sichereren Art interessiert, die du in deiner Antwort erklärt hast. Kannst du das bitte auch dafür liefern JSON: Nochmals vielen Dank. –

+0

Eigentlich muss ich nur eine äquivalente Struktur haben, die den JSON und Unmarshal darstellt (wenn du das meinst). Ich kann das selbst ausprobieren, wenn Sie ein paar Hinweise geben. Vielen Dank. –

+1

@GauravSinha Yep, das ist was ich meine und hier ist ein Beispiel dafür; https://play.golang.org/p/VfHst9GaiR Ich werde einige der relevanten Code in meine Antwort veröffentlichen, obwohl ich eine Menge schlampige Sachen getan habe, nur um zu beweisen, dass die Daten da sind/zeigen, wie man darauf zugreifen kann. – evanmcdonnal