golang json go

bind json golang



Deshacerse de los objetos JSON anidados en Golang (8)

¿Hay alguna manera de desasignar la propiedad de barra anidada y asignarla directamente a una propiedad de estructura sin crear una estructura anidada?

No, encoding / json no puede hacer el truco con "> some> deep> childnode" como encoding / xml puede hacer. Estructuras anidadas es el camino a seguir.

Hay few questions sobre el topic pero ninguna parece cubrir mi caso, así que estoy creando una nueva.

Tengo JSON como el siguiente:

{"foo":{ "bar": "1", "baz": "2" }, "more": "text"}

¿Hay alguna manera de desasignar la propiedad de barra anidada y asignarla directamente a una propiedad de estructura sin crear una estructura anidada?

La solución que estoy adoptando ahora es la siguiente:

type Foo struct { More String `json:"more"` Foo struct { Bar string `json:"bar"` Baz string `json:"baz"` } `json:"foo"` // FooBar string `json:"foo.bar"` }

Esta es una versión simplificada, por favor ignore la verbosidad. Como puede ver, me gustaría poder analizar y asignar el valor a

// FooBar string `json:"foo.bar"`

He visto personas usando un mapa, pero ese no es mi caso. Básicamente no me importa el contenido de foo (que es un objeto grande), excepto por algunos elementos específicos.

¿Cuál es el enfoque correcto en este caso? No estoy buscando hacks extraños, así que si este es el camino a seguir, estoy de acuerdo con eso.


¿Qué hay de los campos anónimos? No estoy seguro de si eso constituirá una "estructura anidada", pero es más claro que tener una declaración de estructura anidada. ¿Qué sucede si quiere reutilizar el elemento anidado en otro lugar?

type NestedElement struct{ someNumber int `json:"number"` someString string `json:"string"` } type BaseElement struct { NestedElement `json:"bar"` }


Al igual que lo que Volker mencionó, las estructuras anidadas es el camino a seguir. Pero si realmente no desea estructuras anidadas, puede anular el func UnmarshalJSON.

http://play.golang.org/p/T0aZEDL0Nu

type A struct { FooBar string // takes foo.bar FooBaz string // takes foo.baz More string `json:"more"` } func (a *A) UnmarshalJSON(b []byte) error { var f interface{} json.Unmarshal(b, &f) m := f.(map[string]interface{}) foomap := m["foo"] v := foomap.(map[string]interface{}) a.FooBar = v["bar"].(string) a.FooBaz = v["baz"].(string) return nil }

Por favor, ignore el hecho de que no estoy devolviendo un error apropiado. Lo dejé por simplicidad.


Estaba trabajando en algo como esto. Pero está trabajando solo con estructuras generadas desde proto. https://github.com/flowup-labs/grpc-utils

en tu proto

message Msg { Firstname string = 1 [(gogoproto.jsontag) = "name.firstname"]; PseudoFirstname string = 2 [(gogoproto.jsontag) = "lastname"]; EmbedMsg = 3 [(gogoproto.nullable) = false, (gogoproto.embed) = true]; Lastname string = 4 [(gogoproto.jsontag) = "name.lastname"]; Inside string = 5 [(gogoproto.jsontag) = "name.inside.a.b.c"]; } message EmbedMsg{ Opt1 string = 1 [(gogoproto.jsontag) = "opt1"]; }

Entonces su salida será

{ "lastname": "Three", "name": { "firstname": "One", "inside": { "a": { "b": { "c": "goo" } } }, "lastname": "Two" }, "opt1": "var" }


Este es un ejemplo de cómo deshacer las respuestas JSON del servidor proxy sbserver de Safebrowsing v4 API: https://play.golang.org/p/4rGB5da0Lt

// this example shows how to unmarshall JSON requests from the Safebrowsing v4 sbserver package main import ( "fmt" "log" "encoding/json" ) // response from sbserver POST request type Results struct { Matches []Match } // nested within sbserver response type Match struct { ThreatType string PlatformType string ThreatEntryType string Threat struct { URL string } } func main() { fmt.Println("Hello, playground") // sample POST request // curl -X POST -H ''Content-Type: application/json'' // -d ''{"threatInfo": {"threatEntries": [{"url": "http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/"}]}}'' // http://127.0.0.1:8080/v4/threatMatches:find // sample JSON response jsonResponse := `{"matches":[{"threatType":"MALWARE","platformType":"ANY_PLATFORM","threatEntryType":"URL","threat":{"url":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/"}}]}` res := &Results{} err := json.Unmarshal([]byte(jsonResponse), res) if(err!=nil) { log.Fatal(err) } fmt.Printf("%v/n",res) fmt.Printf("/tThreat Type: %s/n",res.Matches[0].ThreatType) fmt.Printf("/tPlatform Type: %s/n",res.Matches[0].PlatformType) fmt.Printf("/tThreat Entry Type: %s/n",res.Matches[0].ThreatEntryType) fmt.Printf("/tURL: %s/n",res.Matches[0].Threat.URL) }


La combinación de map y struct permite desasignar objetos JSON anidados donde la clave es dinámica. => mapa [cadena]

Por ejemplo: stock.json

{ "MU": { "symbol": "MU", "title": "micro semiconductor", "share": 400, "purchase_price": 60.5, "target_price": 70 }, "LSCC":{ "symbol": "LSCC", "title": "lattice semiconductor", "share": 200, "purchase_price": 20, "target_price": 30 } }

Ir a la aplicación

package main import ( "encoding/json" "fmt" "io/ioutil" "log" "os" ) type Stock struct { Symbol string `json:"symbol"` Title string `json:"title"` Share int `json:"share"` PurchasePrice float64 `json:"purchase_price"` TargetPrice float64 `json:"target_price"` } type Account map[string]Stock func main() { raw, err := ioutil.ReadFile("stock.json") if err != nil { fmt.Println(err.Error()) os.Exit(1) } var account Account log.Println(account) }

La clave dinámica en el hash es manejar una cadena, y el objeto anidado está representado por una estructura.


Sí. Con gjson todo lo que tienes que hacer ahora es:

bar := gjson.Get(json, "foo.bar")

bar podría ser una propiedad de estructura si lo desea. Además, no hay mapas.


sí puede asignar los valores de json anidado a struct hasta que conozca el tipo subyacente de claves json, por ejemplo.

package main import ( "encoding/json" "fmt" ) // Object type Object struct { Foo map[string]map[string]string `json:"foo"` More string `json:"more"` } func main(){ someJSONString := []byte(`{"foo":{ "bar": "1", "baz": "2" }, "more": "text"}`) var obj Object err := json.Unmarshal(someJSONString, &obj) if err != nil{ fmt.Println(err) } fmt.Println("jsonObj", obj) }