Rumah > pembangunan bahagian belakang > Golang > Memanggil json.Unmarshal dalam fungsi UnmarshalJSON tidak menyebabkan limpahan tindanan

Memanggil json.Unmarshal dalam fungsi UnmarshalJSON tidak menyebabkan limpahan tindanan

WBOY
Lepaskan: 2024-02-12 08:27:09
ke hadapan
598 orang telah melayarinya

在 UnmarshalJSON 函数内调用 json.Unmarshal 不会导致堆栈溢出

Apabila memproses data JSON, kami biasanya menggunakan fungsi json.Unmarshal untuk menghuraikan rentetan JSON ke dalam struktur dalam bahasa Go. Walau bagaimanapun, memanggil fungsi json.Unmarshal dalam fungsi UnmarshalJSON boleh menyebabkan ralat limpahan tindanan. Ini kerana fungsi UnmarshalJSON memanggil dirinya semula apabila menghuraikan data JSON, menyebabkan gelung tak terhingga. Untuk mengelakkan ini, kita boleh menggunakan kaedah Nyahkod json.Decoder untuk menghuraikan data JSON dan bukannya memanggil fungsi json.Unmarshal secara langsung. Melakukan ini memastikan bahawa masalah limpahan tindanan tidak akan berlaku dan memastikan keteguhan dan prestasi kod.

Kandungan soalan

Saya ingin melakukan beberapa langkah tambahan untuk memulakan pelaksanaan saya UnmarshalJSON 中的数据结构。在该实现中调用 json.Unmarshal(b, type) yang secara semula jadi mengakibatkan limpahan tindanan.

Penyahkod JSON terus mencuba untuk mencari jika ada tersuai UnmarshalJSON 实现,然后再次调用 json.Unmarshal.

Adakah ada cara lain untuk melakukan ini? Bukankah hanya memanggil pelaksanaan lalai yang mendasari menyebabkan masalah ini?

Penyelesaian

Cara mudah dan biasa untuk mengelakkan ini/mencegah ini adalah dengan menggunakan kata kunci type dan gunakan jenis penukaran untuk lulus nilai jenis itu (nilai boleh digunakan jika anda nilai primitif, penukaran jenis adalah mungkin kerana jenis baharu mempunyai jenis primitif sebagai jenis asasnya).

Ini berfungsi kerana kata kunci type mencipta jenis baharu dan jenis baharu akan mempunyai kaedah sifar (ia tidak akan "mewarisi" kaedah jenis asas).

Adakah ini memerlukan overhed masa jalan? tidak. Dipetik daripada Spesifikasi: Penukaran:

Mari kita lihat contoh. Kami ada satu dengan nombor AgePerson 类型,并且我们要确保 Age 不能为负数(小于 0).

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

func (p *Person) UnmarshalJSON(data []byte) error {
    type person2 Person
    if err := json.Unmarshal(data, (*person2)(p)); err != nil {
        return err
    }

    // Post-processing after unmarshaling:
    if p.Age < 0 {
        p.Age = 0
    }
    return nil
}
Salin selepas log masuk

Uji:

var p *Person
fmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":10}`), &p))
fmt.Println(p)

fmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":-1}`), &p))
fmt.Println(p)
Salin selepas log masuk

Output (cuba di Go Playground):

<nil>
&{Bob 10}
<nil>
&{Bob 0}
Salin selepas log masuk

Sudah tentu, teknik yang sama juga berfungsi untuk marshal tersuai (MarshalJSON()):

func (p *Person) MarshalJSON() ([]byte, error) {
    // Pre-processing before marshaling:
    if p.Age < 0 {
        p.Age = 0
    }

    type person2 Person
    return json.Marshal((*person2)(p))
}
Salin selepas log masuk

Uji:

p = &Person{"Bob", 10}
fmt.Println(json.NewEncoder(os.Stdout).Encode(p))
p = &Person{"Bob", -1}
fmt.Println(json.NewEncoder(os.Stdout).Encode(p))
Salin selepas log masuk

Output (dalam contoh Go Playground yang sama):

{"name":"Bob","age":10}
<nil>
{"name":"Bob","age":0}
<nil>
Salin selepas log masuk

Masalah yang hampir sama ialah apabila anda menambah kaedah fmt 的自定义文本表示定义 String() string pada pakej a> dan anda mahu menggunakan perwakilan rentetan lalai yang anda ubah suai. Baca lebih lanjut mengenainya di sini: Perbezaan antara t dan *t

Atas ialah kandungan terperinci Memanggil json.Unmarshal dalam fungsi UnmarshalJSON tidak menyebabkan limpahan tindanan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan