【问题标题】:How to json unmarshalling with custom attribute type in Go如何在 Go 中使用自定义属性类型进行 json 解组
【发布时间】:2019-09-13 10:50:19
【问题描述】:

在我的项目中,我定义了从 JSON 获取数据的结构。 我尝试使用json.Unmarshal() 函数。但它不适用于自定义类型属性。

有这样的结构:

type TestModel struct {
    ID   NullInt `json:"id"`
    Name string  `json:"name"`
}

在那里,NullInt 类型是用 MarshalJSON()UnmarshalJSON() 函数的实现定义的:

// NullInt ...
type NullInt struct {
    Int   int
    Valid bool
}

// MarshalJSON ...
func (ni NullInt) MarshalJSON() ([]byte, error) {
    if !ni.Valid {
        return []byte("null"), nil
    }
    return json.Marshal(ni.Int)
}

// UnmarshalJSON ...
func (ni NullInt) UnmarshalJSON(b []byte) error {
    fmt.Println("UnmarshalJSON...")
    err := json.Unmarshal(b, &ni.Int)
    ni.Valid = (err == nil)
    fmt.Println("NullInt:", ni)
    return err
}

main()函数中,我实现了:

func main() {
    model := new(TestModel)
    JSON := `{
        "id": 1,
        "name": "model" 
    }`
    json.Unmarshal([]byte(JSON), &model)
    fmt.Println("model.ID:", model.ID) 
}

在控制台中,我得到:

UnmarshalJSON...
NullInt: {1 true}
model.ID: {0 false}

如您所见,NullInt.UnmarshalJSON() 被调用,ni 是我所期望的,但 model.ID 的值。 UnmarshalJSON()函数的正确实现方式是什么?

另外,当我设置:JSON := `{"name": "model"}`(没有id)时,控制台只是:

model.ID: {0 false}

这意味着,UnmarshalJSON() 函数没有被调用,那么我没有以正确的方式获得 model.ID 的值。

【问题讨论】:

    标签: json pointers go struct unmarshalling


    【解决方案1】:

    UnmarshalJSON()需要修改receiver,所以必须使用指针receiver:

    func (ni *NullInt) UnmarshalJSON(b []byte) error {
        // ...
    }
    

    接收者和所有参数只是副本,如果不使用指针,则只能修改副本,该副本将在方法返回后被丢弃。如果你使用指针接收器,那也只是一个副本,但指向的值将是相同的,因此你可以修改原始(指向)对象。

    为了一致性,其他方法也使用指针接收器。

    通过此更改,它可以工作并输出(在Go Playground 上尝试):

    UnmarshalJSON...
    NullInt: &{1 true}
    model.ID: {1 true}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多