Jadual Kandungan
Kandungan soalan
Penyelesaian
Rumah pembangunan bahagian belakang Golang Buat objek json secara manual dari struct dalam golang

Buat objek json secara manual dari struct dalam golang

Feb 12, 2024 am 11:03 AM
overflow

Buat objek json secara manual dari struct dalam golang

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!

Kandungan soalan

Saya ada struktur untuk katakan

<code>type Foo struct {
  A string `json:",omitemtpy"
}
</code>
Salin selepas log masuk

Saya tahu saya boleh menukarnya dengan mudah kepada json menggunakan sesuatu seperti ini

json.Marshal(Foo{})
Salin selepas log masuk

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)
Salin selepas log masuk

Keluaran:

dup FooWithPtrs:
    {"String":"helloWorld","Int":0,"Bar":null} <nil>
Salin selepas log masuk

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)
}
Salin selepas log masuk

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"`
}
Salin selepas log masuk

Pertama, berikut ialah output JSON tanpa pertindihan jenis:

data, err := json.Marshal(Foo{})
fmt.Println("Foo:\n", string(data), err)
Salin selepas log masuk

Keluaran:

Foo:
 {"Bar":{"Baz":{}}} <nil>
Salin selepas log masuk

Perhatikan bahawa kami mendapat medan Bar<code>BarBaz 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(&quot;dup Foo:\n&quot;, 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: {&quot;String&quot;:&quot;&quot;,&quot;Int&quot;:0,&quot;Bar&quot;:{&quot;Float&quot;:0,&quot;PtrInt&quot;:0,&quot;Baz&quot;:{&quot;XXXX&quot;:0}}} &lt;nil&gt;</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:&quot;String,omitempty&quot;` Int int `json:&quot;,omitempty&quot;` Bar *struct { Float float64 `json:&quot;,omitempty&quot;` PtrInt int `json:&quot;,omitempty&quot;` Baz *struct { X int `json:&quot;XXXX,omitempty&quot;` } `json:&quot;,omitempty&quot;` } `json:&quot;,omitempty&quot;` }</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(&quot;dup FooWithPtrs:\n&quot;, 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: {&quot;String&quot;:&quot;&quot;,&quot;Int&quot;:0,&quot;Bar&quot;:null} &lt;nil&gt;</pre><div class="contentsignin">Salin selepas log masuk</div></div> <code>null,但我们也希望它们的字段也出现在输出中。这需要将它们初始化为非 nilJika struct mengandungi penunjuk, penunjuk ini muncul sebagai null dalam output JSON

, tetapi kami mahu medan mereka muncul dalam output juga. Ini memerlukan permulaannya kepada nilai bukannihil

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))
        }
    }
}
Salin selepas log masuk

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)
Salin selepas log masuk

Keluaran:

dup and inited FooWithPtrs:
 {"String":"","Int":0,"Bar":{"Float":0,"PtrInt":0,"Baz":{"XXXX":0}}} <nil>
Salin selepas log masuk
🎜Tidak teruk! Ia mengandungi semua bidang! 🎜

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!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Tag artikel panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Harga Bitcoin sejak kelahirannya 2009-2025 Ringkasan paling lengkap harga sejarah BTC Harga Bitcoin sejak kelahirannya 2009-2025 Ringkasan paling lengkap harga sejarah BTC Jan 15, 2025 pm 08:11 PM

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 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 May 06, 2024 pm 01:20 PM

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? Adakah terdapat forum komuniti atau kumpulan perbincangan untuk fungsi Java di mana saya boleh bertanya dan membincangkannya? Apr 28, 2024 pm 02:12 PM

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 Bagaimana untuk menggunakan kod orang lain dalam python May 05, 2024 pm 07:54 PM

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 Apakah yang perlu saya lakukan jika masa pada komputer win11 saya sentiasa salah? Bagaimana untuk melaraskan masa yang salah pada komputer Windows 11 May 03, 2024 pm 09:20 PM

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 Jenis pengecualian biasa dan langkah pembaikan mereka dalam pembangunan fungsi Java May 03, 2024 pm 02:09 PM

Jenis pengecualian biasa dan langkah pembaikan mereka dalam pembangunan fungsi Java

Apakah maksud limpahan dalam css Apakah maksud limpahan dalam css Apr 28, 2024 pm 03:15 PM

Apakah maksud limpahan dalam css

Adakah tiada sesiapa yang menjaga akaun rawak Douyin? Bolehkah saya membuat rayuan untuk kali kedua? Adakah tiada sesiapa yang menjaga akaun rawak Douyin? Bolehkah saya membuat rayuan untuk kali kedua? May 03, 2024 am 09:37 AM

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

See all articles