Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Mengekalkan Marshalling Tersuai dalam Struktur Terbenam Go?

Bagaimana untuk Mengekalkan Marshalling Tersuai dalam Struktur Terbenam Go?

DDD
DDDasal
2024-12-17 19:07:10857semak imbas

How to Preserve Custom Marshalling in Go Embedded Structs?

Memelihara Marshalling Tersuai untuk Struktur Terbenam

Dalam Go, membenamkan satu struct ke yang lain ialah cara biasa untuk mewarisi kefungsian. Walau bagaimanapun, apabila struct terbenam mempunyai kaedah MarshalJSON() tersuai, isu boleh timbul. Artikel ini meneroka penyelesaian kepada cabaran ini, memastikan bahawa struct luar boleh menyusun medannya secara normal sambil masih memanfaatkan marshalling tersuai bagi struct terbenam.

Pertimbangkan struct berikut:

type Person struct {
    Name string `json:"name"`
}

type Employee struct {
    *Person
    JobRole string `json:"jobRole"`
}

Biasanya, menggabungkan Pekerja kepada JSON akan menghasilkan yang diharapkan output:

p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
// Output: {"name":"Bob","jobRole":"Sales"}

Walau bagaimanapun, memperkenalkan kaedah MarshalJSON() tersuai untuk struct Person terbenam mengubah tingkah laku ini:

func (p *Person) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{ Name string `json:"name"` }{Name: strings.ToUpper(p.Name)})
}

Sekarang, marshalling Employee hanya menghasilkan nama huruf besar:

output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
// Output: {"name":"BOB"}

Untuk menyelesaikan masalah ini, seseorang mungkin cuba menambah kaedah MarshalJSON() pada struktur Pekerja luar. Walau bagaimanapun, pendekatan ini memerlukan pengetahuan tentang marshalling tersuai jenis terbenam, yang mungkin tidak selalu praktikal.

Penyelesaian yang lebih generik melibatkan pelaksanaan terus MarshalJSON() pada jenis luar:

// Note: not on Person
func (e *Employee) MarshalJSON() ([]byte, error) {
    inner, err := json.MarshalIndent((*e.Person).(*Person), "", "    ")
    if err != nil {
        return nil, err
    }

    b := []byte(strings.Replace(string(inner), "}", "}", -1))
    b = append(b, []byte(`,"jobRole":"`+e.JobRole+`"}`)...)

    return b, nil
}

Pendekatan ini memanggil kaedah MarshalJSON() struct terbenam, menukar hasilnya kepada peta dan menambah medan struct luar untuk menghasilkan output JSON yang dikehendaki. Ambil perhatian bahawa ia tidak memanipulasi marshalling tersuai struct terbenam.

Sebagai alternatif, seseorang boleh menggunakan pendekatan berasaskan refleksi:

func (e *Employee) MarshalJSON() ([]byte, error) {
    v := reflect.ValueOf(e).Elem()
    vf := v.FieldByName("Person")
    tmp, err := json.MarshalIndent(vf.Interface(), "", "    ")
    if err != nil {
        return nil, err
    }

    return []byte(strings.Replace(string(tmp), "}", `,"jobRole":"`+e.JobRole+`"}`, -1)), nil
}

Kaedah ini menggunakan refleksi untuk mengakses nilai dan medan struct terbenam , membolehkan marshalling tersuai tanpa bergantung pada pengetahuan struktur.

Dengan melaksanakan MarshalJSON() pada jenis luar, pendekatan ini memastikan bahawa kedua-dua medan struktur terbenam dan luar disusun dengan betul, mengekalkan output yang diingini.

Atas ialah kandungan terperinci Bagaimana untuk Mengekalkan Marshalling Tersuai dalam Struktur Terbenam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
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