首頁 >後端開發 >Golang >在 UnmarshalJSON 函數內呼叫 json.Unmarshal 不會導致堆疊溢位

在 UnmarshalJSON 函數內呼叫 json.Unmarshal 不會導致堆疊溢位

WBOY
WBOY轉載
2024-02-12 08:27:09611瀏覽

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

在處理 JSON 資料時,我們通常會使用 json.Unmarshal 函數將 JSON 字串解析為 Go 語言中的結構體。然而,在 UnmarshalJSON 函數內部呼叫 json.Unmarshal 函數可能會導致堆疊溢位的錯誤。這是因為 UnmarshalJSON 函數在解析 JSON 資料時會再次呼叫自身,進而導致無限迴圈。為了避免這種情況,我們可以使用 json.Decoder 的 Decode 方法來解析 JSON 數據,而不是直接呼叫 json.Unmarshal 函數。這樣做可以確保不會造成堆疊溢位的問題,並確保程式碼的健全性和效能。

問題內容

我想執行一些額外的步驟來初始化我的實作 UnmarshalJSON 中的資料結構。在該實作中呼叫 json.Unmarshal(b, type) 自然會導致堆疊溢位。

JSON 解碼器不斷嘗試尋找是否有自訂 UnmarshalJSON 實現,然後再次呼叫 json.Unmarshal

還有其他方法可以做到這一點嗎?只需呼叫底層預設實作就不會導致此問題?

解決方法

避免這種情況/防止這種情況的簡單而常見的方法是使用type 關鍵字,並使用類型conversion 來傳遞該類型的值(該值可以如果是您的原始值,則可以進行類型轉換,因為新類型將原始類型作為其基礎類型)。

這是有效的,因為 type 關鍵字建立了一個新類型,並且新類型將具有零個方法(它不會「繼承」基礎類型的方法)。

這會產生一些運行時開銷嗎?否。引用自 規格:轉換:

#

讓我們來看一個例子。我們有一個帶有數字 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
}

測試它:

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)

輸出(在 Go Playground 上嘗試):

<nil>
&{Bob 10}
<nil>
&{Bob 0}

當然,相同的技術也適用於自訂封送處理(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))
}

測試它:

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

輸出(在同一個 Go Playground 範例中):

{"name":"Bob","age":10}
<nil>
{"name":"Bob","age":0}
<nil>

一個非常相似的問題是,當您為fmt 的自訂文字表示定義 的自定义文本表示定义 String() string 方法時a> 包,並且您想若要使用您修改的預設字串表示形式。在這裡閱讀更多相關資訊:t 和 *t 之間的差異

#

以上是在 UnmarshalJSON 函數內呼叫 json.Unmarshal 不會導致堆疊溢位的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除