26 December 2019

golang自带的json解析中,若是声明的字段类型和实际传入的类型不同,会报错。例如:

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

若是实际传入的User.ID是个string类型,golang会报错。一般情况下,可以通过在声明中添加json字段的类型说明来解决,例如

type User struct {
    ID   int    `json:"id,string"`
    Name string `json:"name"`
}

假设有这种情况,由于历史原因,ID字段可能会传入stringint(实际上,在json中是浮点数),这时将ID字段声明为string是不行的,golang不会自动将int型的内容自动转换为string。需要手动做一次转换,例如:

type userWrapper struct {
    ID   interface{} `json:"id"`
    Name string      `json:"name"`
}

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

func (u *User) UnmarshalJSON(b []byte) (err error) {
    d := json.NewDecoder(strings.NewReader(string(b)))
    d.UseNumber()

    var uw userWrapper
    if err := d.Decode(&uw); err != nil {
        return err
    }

    u.Name = uw.Name
    u.Uid = fmt.Sprintf("%v", uw.Uid)
    return nil
}

在上面的代码中,额外多做了一步d.UseNumber()。这样做是为了避免Uid被表示为科学计数法。