如何在Go中使用自定义属性类型对JSON解组 [英] How to json unmarshalling with custom attribute type in Go

查看:74
本文介绍了如何在Go中使用自定义属性类型对JSON解组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my project, I've defined structures so that get data from JSON. I tried to use json.Unmarshal() function. But it did not work for custom type attribute.

有这样的结构:

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

在其中,使用MarshalJSON()UnmarshalJSON()函数的实现定义了NullInt类型:

In there, NullInt type was defined with implementations of MarshalJSON() and UnmarshalJSON() functions:

// 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) 
}

在控制台中,我得到了:

In console, I got:

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

如您所见,NullInt.UnmarshalJSON()被调用,而ni是我所期望的,但model.ID的值. 什么是实现UnmarshalJSON()功能的正确方法?

As you can see, NullInt.UnmarshalJSON() was called and ni was what I expected but model.ID's value. What is the right way to implement UnmarshalJSON() function?

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

To addition, when I set: JSON := `{"name": "model"}` (without id), console just was:

model.ID: {0 false}

这意味着没有调用UnmarshalJSON()函数,然后我没有以正确的方式获取model.ID的值.

That means, the UnmarshalJSON() function wasn't called then I didn't get model.ID's value in right way.

推荐答案

UnmarshalJSON()需要修改接收器,因此必须使用指针接收器:

UnmarshalJSON() needs to modify the receiver, so you must use pointer receiver:

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

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

The receiver and all parameters are just copies, and if you don't use a pointer, you may only modify a copy which will be discarded once the method returns. If you use a pointer receiver, that is also just a copy, but the pointed value will be the same, hence you may modify the original (pointed) object.

为了保持一致性,还可以将指针接收器用于其其他方法.

For consistency, also use pointer receiver for its other methods.

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

With this change it works and outputs (try it on the Go Playground):

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

这篇关于如何在Go中使用自定义属性类型对JSON解组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆