Objets JSON imbriqués dans Golang
Il y a un quelques questions sur le sujet , mais aucun d'entre eux semblent couvrir mon cas, donc je suis en créer un nouveau.
j'ai JSON comme suit:
{"foo":{ "bar": "1", "baz": "2" }, "more": "text"}
y a-t-il un moyen de démasquer la propriété Bar imbriquée et de l'attribuer directement à une propriété struct sans créer une structure imbriquée?
le la solution que j'adopte maintenant est la suivante:
type Foo struct {
More String `json:"more"`
Foo struct {
Bar string `json:"bar"`
Baz string `json:"baz"`
} `json:"foo"`
// FooBar string `json:"foo.bar"`
}
ceci est une version simplifiée, s'il vous plaît ignorez la verbosité. Comme vous pouvez le voir, j'aimerais pouvoir analyser et attribuer la valeur à
// FooBar string `json:"foo.bar"`
j'ai vu des gens utiliser une carte, mais ce n'est pas mon cas. Fondamentalement, Je ne me soucie pas du contenu de foo
(qui est un grand objet), sauf pour quelques éléments spécifiques.
Quelle est l'approche correcte dans ce cas? Je ne suis pas à la recherche de piratages bizarres, donc si c'est le chemin à suivre, je suis d'accord avec ça.
8 réponses
y a-t-il un moyen de démasquer la propriété Bar imbriquée et de l'attribuer directement à une propriété struct sans créer une structure imbriquée?
Non, encodage/json ne peut pas faire le truc avec ">>profondeur>childnode" comme l'encodage/xml peut faire. Les structures imbriquées sont la voie à suivre.
comme Volker l'a mentionné, les structures imbriquées sont la voie à suivre. Mais si vous vraiment ne voulez pas de structures imbriquées, vous pouvez outrepasser le 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
}
s'il vous plaît ignorez le fait que je ne retourne pas une erreur correcte. J'ai quitté pour des raisons de simplicité.
Ceci est un exemple de comment désactiver les réponses JSON de Safebrowsing V4 API sbserver proxy server: 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)
}
Oui. Avec gjson tout ce que vous avez à faire maintenant est:
bar := gjson.Get(json, "foo.bar")
bar
pourrait être une propriété struct si vous voulez. Aussi, pas de cartes.
et les champs anonymes? Je ne suis pas sûr que cela constituera une "structure imbriquée" mais c'est plus propre que d'avoir une déclaration de structure imbriquée. Si vous souhaitez réutiliser l'élément imbriqué ailleurs?
type NestedElement struct{
someNumber int `json:"number"`
someString string `json:"string"`
}
type BaseElement struct {
NestedElement `json:"bar"`
}
oui vous pouvez assigner les valeurs de JSON imbriqué à struct jusqu'à ce que vous connaissiez le type sous-jacent de clés json par exemple.
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)
}
je travaillais sur quelque chose comme ça. Mais fonctionne uniquement avec des structures générées à partir de proto. https://github.com/flowup-labs/grpc-utils
dans votre 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"];
}
alors votre sortie sera
{
"lastname": "Three",
"name": {
"firstname": "One",
"inside": {
"a": {
"b": {
"c": "goo"
}
}
},
"lastname": "Two"
},
"opt1": "var"
}
combinant map et struct permettent de désamorcer les objets JSON imbriqués où la clé est dynamique. => carte[string]
par exemple: 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
}
}
Aller de l'application
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 clé dynamique dans le hachage est manier une chaîne, et l'objet imbriqué est représenté par une structure.