Erstellen Sie manuell ein JSON-Objekt aus einer Struktur in Golang

WBOY
Freigeben: 2024-02-12 11:03:08
nach vorne
1014 Leute haben es durchsucht

Erstellen Sie manuell ein JSON-Objekt aus einer Struktur in Golang

In Golang ist das manuelle Erstellen von JSON-Objekten aus einer Struktur ein häufiger Vorgang. Durch die Konvertierung der Struktur in das JSON-Format können wir sie problemlos für die Netzwerkübertragung oder -speicherung verwenden. In diesem Artikel stellt Ihnen der PHP-Editor Banana vor, wie Sie das integrierte Paket von Golang verwenden, um diese Funktion zu erreichen. Darüber hinaus werden wir untersuchen, wie man mit verschachtelten Feldern in Strukturen umgeht und wie man mit speziellen Feldtypen umgeht. Unabhängig davon, ob Sie Anfänger oder erfahrener Entwickler sind, bietet Ihnen dieser Artikel detaillierte Anleitungen, die Ihnen beim einfachen Erstellen von JSON-Objekten in Golang helfen. Lasst uns beginnen!

Frageninhalt

Ich muss eine Struktur sagen

type Foo struct { A string `json:",omitemtpy" } 
Nach dem Login kopieren

Ich weiß, dass ich es mit so etwas leicht in JSON konvertieren kann

json.Marshal(Foo{})
Nach dem Login kopieren

Es wird eine leere JSON-Zeichenfolge zurückgegeben.

Aber ich muss dieselbe Struktur verwenden, um die JSON-Darstellung der Struktur mit allen im JSON vorhandenen Feldern und „Nullwerten“ zurückzugeben. (Eigentlich ist es eine sehr große Struktur, daher kann ich nicht einfach eine Kopie ohne die Tags behalten)

Was ist der einfachste Weg?

Grundsätzlich muss ich einen JSON-Marshal einer Struktur erstellen, die das JSON-Omitempty-Tag ignoriert.

Diese JSON-Erstellung muss nicht effizient oder leistungsfähig sein.

Für diese Art von Aufgabe hätte ich eine Bibliothek vorgezogen, aber die meisten Bibliotheken, die ich gesehen habe, haben entweder ein spezielles Format erstellt oder omitempty respektiert

Herausgeber:

Wählen Sie https://stackoverflow.com/a/77799949/2187510 als meine Antwort und führen Sie zusätzliche Arbeiten aus, um Standardwerte zuzulassen (unter Verwendung des Codes als Referenz)

defaultFoo := FoodWithPts{ Str: "helloWorld"} dupFooType := dupType(reflect.TypeOf(defaultFoo)) foo := reflect.Zero(dupFooType).Interface() // New additions defaults, _ := json.Marshal(defaultFoo) json.Unmarshal(defaults, &foo) // overwrites foo with defaults // End New additions data, err := json.Marshal(foo) fmt.Println("dup FooWithPtrs:\n", string(data), err)
Nach dem Login kopieren

Ausgabe:

dup FooWithPtrs: {"String":"helloWorld","Int":0,"Bar":null} 
Nach dem Login kopieren

Workaround

Sie können Tags zur Laufzeit nicht ändern, aber Sie können Strukturtypen zur Laufzeit erstellen, indem Sie$$c$$reflect.StructOf()verwenden.

Die Idee besteht also darin, den Strukturtyp zu kopieren, aber die Option,omitempty,omitemptyaus dem JSON-Tag bei der Duplizierung auszuschließen.

Alle Beispiele finden Sie unten aufGo Playground.

Es ist einfacher, als die Leute zuerst denken. Wir müssen es nur rekursiv machen (ein Strukturfeld kann eine andere Struktur sein) und wir sollten uns auf jeden Fall mit Zeigern befassen:

func dupType(t reflect.Type) reflect.Type { if t.Kind() == reflect.Pointer { return reflect.PointerTo(dupType(t.Elem())) } if t.Kind() != reflect.Struct { return t } var fields []reflect.StructField for i := 0; i < t.NumField(); i++ { sf := t.Field(i) sf.Type = dupType(sf.Type) // Keep json tag but cut ,omitempty option if exists: if tag, _ := strings.CutSuffix(sf.Tag.Get("json"), ",omitempty"); tag == "" { sf.Tag = "" } else { sf.Tag = `json:"` + reflect.StructTag(tag) + `"` } fields = append(fields, sf) } return reflect.StructOf(fields) }
Nach dem Login kopieren

Lassen Sie es uns mit diesem Typ testen:

type Foo struct { Str string `json:"String,omitempty"` Int int `json:",omitempty"` Bar struct { Float float64 `json:",omitempty"` PtrInt int `json:",omitempty"` Baz struct { X int `json:"XXXX,omitempty"` } `json:",omitempty"` } `json:",omitempty"` }
Nach dem Login kopieren

Hier ist zunächst die JSON-Ausgabe ohne Typduplizierung:

data, err := json.Marshal(Foo{}) fmt.Println("Foo:\n", string(data), err)
Nach dem Login kopieren

Ausgabe:

Foo: {"Bar":{"Baz":{}}} 
Nach dem Login kopieren

Beachten Sie, dass wir die FelderBarBarBazundBaz

erhalten haben, weil es sich um Strukturen handelt.

Lassen Sie uns versuchen, Folgendes einzugeben:

dupFooType := dupType(reflect.TypeOf(Foo{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println("dup Foo:\n", string(data), err)
Nach dem Login kopieren

Dies wird ausgegeben:

dup Foo: {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
Nach dem Login kopieren

Nicht schlecht! Genau das, was wir wollten!

Aber wir sind noch nicht fertig. Was wäre, wenn wir einen Typ mit einem Strukturzeigerfeld hätten? So:

type FooWithPtrs struct { Str string `json:"String,omitempty"` Int int `json:",omitempty"` Bar *struct { Float float64 `json:",omitempty"` PtrInt int `json:",omitempty"` Baz *struct { X int `json:"XXXX,omitempty"` } `json:",omitempty"` } `json:",omitempty"` }
Nach dem Login kopieren

Versuchen Sie es mit dem JSON-Marshalling von Werten wiederholter Typen:

dupFooType := dupType(reflect.TypeOf(FooWithPtrs{})) foo := reflect.Zero(dupFooType).Interface() data, err := json.Marshal(foo) fmt.Println("dup FooWithPtrs:\n", string(data), err)
Nach dem Login kopieren

Ausgabe:

dup FooWithPtrs: {"String":"","Int":0,"Bar":null} <nil>
Nach dem Login kopieren
null,但我们也希望它们的字段也出现在输出中。这需要将它们初始化为非nilWenn die Struktur Zeiger enthält, erscheinen diese Zeiger alsnull in der JSON-Ausgabe

, aber wir möchten, dass ihre Felder auch in der Ausgabe erscheinen. Dies erfordert die Initialisierung mit Nicht-Null

-Werten, damit sie eine Ausgabe erzeugen.

Glücklicherweise können wir dies auch durch Reflexion tun:

func initPtrs(v reflect.Value) { if !v.CanAddr() { return } if v.Kind() == reflect.Pointer { v.Set(reflect.New(v.Type().Elem())) v = v.Elem() } if v.Kind() == reflect.Struct { for i := 0; i < v.NumField(); i++ { initPtrs(v.Field(i)) } } }
Nach dem Login kopieren

Wir sind gespannt! Sehen wir es uns in Aktion an:

dupFooType := dupType(reflect.TypeOf(FooWithPtrs{})) fooVal := reflect.New(dupFooType) initPtrs(fooVal.Elem()) data, err := json.Marshal(fooVal.Interface()) fmt.Println("dup and inited FooWithPtrs:\n", string(data), err)
Nach dem Login kopieren

Ausgabe:

dup and inited FooWithPtrs: {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} 
Nach dem Login kopieren
Nicht schlecht! Es enthält alle Felder!

Das obige ist der detaillierte Inhalt vonErstellen Sie manuell ein JSON-Objekt aus einer Struktur in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!