Dalam golang, mencipta objek json secara manual daripada struct ialah operasi biasa. Dengan menukar struct kepada format json, kami boleh menggunakannya dengan mudah dalam penghantaran atau storan rangkaian. Dalam artikel ini, editor PHP Banana akan memperkenalkan anda cara menggunakan pakej terbina dalam golang untuk mencapai fungsi ini. Bukan itu sahaja, kami juga akan meneroka cara menangani medan bersarang dalam struct dan cara menangani jenis medan khas. Sama ada anda seorang pemula atau pembangun yang berpengalaman, artikel ini akan memberikan anda panduan terperinci untuk membantu anda membuat objek json dengan mudah dalam golang. Mari mulakan!
Saya ada struktur untuk katakan
<code>type Foo struct { A string `json:",omitemtpy" } </code>
Saya tahu saya boleh menukarnya dengan mudah kepada json menggunakan sesuatu seperti ini
json.Marshal(Foo{})
Ia akan mengembalikan rentetan json kosong.
Tetapi saya perlu menggunakan struktur yang sama untuk mengembalikan perwakilan json struktur dengan semua medan dan "nilai nol" yang terdapat dalam json. (Sebenarnya, ia adalah struktur yang sangat besar, jadi saya tidak boleh menyimpan salinan tanpa tag)
Apakah cara paling mudah?
Pada asasnya, saya perlu mencipta json marshal bagi struktur yang mengabaikan tag omitempty json.
Penciptaan json ini tidak perlu cekap atau berprestasi.
Saya lebih suka perpustakaan untuk tugasan seperti ini, tetapi kebanyakan perpustakaan yang saya lihat sama ada mencipta beberapa format khas atau menghormati pengabaian
Editor:
Pilih https://stackoverflow.com/a/77799949/2187510 sebagai jawapan saya dan lakukan beberapa kerja tambahan untuk membenarkan nilai lalai (menggunakan kodnya untuk rujukan)
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)
Keluaran:
dup FooWithPtrs: {"String":"helloWorld","Int":0,"Bar":null} <nil>
Anda tidak boleh mengubah suai label pada masa jalan, tetapi anda boleh mencipta jenis struct pada masa jalan menggunakan $$c$$reflect.StructOf().
Jadi ideanya adalah untuk menyalin jenis struct tetapi mengecualikan pilihan ,omitempty<code>,omitempty
daripada tag JSON dalam pendua.
Anda boleh menemui semua contoh di bawah di Go Playground.
Ia lebih mudah daripada yang orang fikirkan pada mulanya. Kita hanya perlu melakukannya secara rekursif (satu medan struct mungkin satu lagi struct), dan kita pasti perlu berurusan dengan petunjuk:
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) }
Mari kita uji dengan jenis ini:
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"` }
Pertama, berikut ialah output JSON tanpa pertindihan jenis:
data, err := json.Marshal(Foo{}) fmt.Println("Foo:\n", string(data), err)
Keluaran:
Foo: {"Bar":{"Baz":{}}} <nil>
Perhatikan bahawa kami mendapat medan Bar<code>Bar
和 Baz
dan Baz</p> kerana ia adalah struct. <p>
</p>Jom cuba taip copy: <p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">dupFooType := dupType(reflect.TypeOf(Foo{}))
foo := reflect.Zero(dupFooType).Interface()
data, err := json.Marshal(foo)
fmt.Println("dup Foo:\n", string(data), err)</pre><div class="contentsignin">Salin selepas log masuk</div></div>
</p>Ini akan menghasilkan: <p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">dup Foo:
{"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil></pre><div class="contentsignin">Salin selepas log masuk</div></div>
</p>Tidak teruk! Apa yang kami mahukan! <p>
</p>Tetapi kami belum selesai. Bagaimana jika kita mempunyai jenis dengan medan penunjuk struktur? Seperti ini: <p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">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"`
}</pre><div class="contentsignin">Salin selepas log masuk</div></div>
</p>Cuba JSON menyusun nilai jenis berulang: <p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">dupFooType := dupType(reflect.TypeOf(FooWithPtrs{}))
foo := reflect.Zero(dupFooType).Interface()
data, err := json.Marshal(foo)
fmt.Println("dup FooWithPtrs:\n", string(data), err)</pre><div class="contentsignin">Salin selepas log masuk</div></div>
</p>Keluaran: <p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">dup FooWithPtrs:
{"String":"","Int":0,"Bar":null} <nil></pre><div class="contentsignin">Salin selepas log masuk</div></div>
<code>null
,但我们也希望它们的字段也出现在输出中。这需要将它们初始化为非 nil
Jika struct mengandungi penunjuk, penunjuk ini muncul sebagai
agar mereka menghasilkan output.
Nasib baik, kita juga boleh menggunakan refleksi untuk melakukan ini:
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)) } } }
Kami teruja! Mari lihat dalam tindakan:
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)
Keluaran:
dup and inited FooWithPtrs: {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
Atas ialah kandungan terperinci Buat objek json secara manual dari struct dalam golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!