Buat objek json secara manual dari struct dalam golang
Feb 12, 2024 am 11:03 AMDalam 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!
Kandungan soalan
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>
Penyelesaian
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!

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Harga Bitcoin sejak kelahirannya 2009-2025 Ringkasan paling lengkap harga sejarah BTC

Perkara yang perlu dilakukan jika masa di sudut kanan bawah Windows 11 hilang_Apa yang perlu dilakukan jika masa di sudut kanan bawah Windows 11 hilang

Adakah terdapat forum komuniti atau kumpulan perbincangan untuk fungsi Java di mana saya boleh bertanya dan membincangkannya?

Bagaimana untuk menggunakan kod orang lain dalam python

Apakah yang perlu saya lakukan jika masa pada komputer win11 saya sentiasa salah? Bagaimana untuk melaraskan masa yang salah pada komputer Windows 11

Jenis pengecualian biasa dan langkah pembaikan mereka dalam pembangunan fungsi Java

Adakah tiada sesiapa yang menjaga akaun rawak Douyin? Bolehkah saya membuat rayuan untuk kali kedua?
