JSON unmarshal integer field into a string

后端 未结 2 544
渐次进展
渐次进展 2021-02-06 10:27

I am struggling with deserializing a integer into a string struct field. The struct field is a string and is expected to be assignable from users of my library. That\'s why I wa

相关标签:
2条回答
  • 2021-02-06 10:47

    You can customize how the data structure is unamrshaled by implementing the json.Unamrshaler interface.

    The simplest way to handle unknown types is to nnmarshal the JSON into an intermediate structure, and handle the type assertions and validation during deserialization:

    type test struct {
        Foo string `json:"foo"`
    }
    
    func (t *test) UnmarshalJSON(d []byte) error {
        tmp := struct {
            Foo interface{} `json:"foo"`
        }{}
    
        if err := json.Unmarshal(d, &tmp); err != nil {
            return err
        }
    
        switch v := tmp.Foo.(type) {
        case float64:
            t.Foo = strconv.Itoa(int(v))
        case string:
            t.Foo = v
        default:
            return fmt.Errorf("invalid value for Foo: %v", v)
        }
    
        return nil
    }
    

    https://play.golang.org/p/t0eI4wCxdB

    0 讨论(0)
  • 2021-02-06 10:48

    To handle big structs you can use embedding.

    Updated to not discard possibly previously set field values.

    func (t *T) UnmarshalJSON(d []byte) error {
        type T2 T // create new type with same structure as T but without its method set!
        x := struct{
            T2 // embed
            Foo json.Number `json:"foo"`
        }{T2: T2(*t)} // don't forget this, if you do and 't' already has some fields set you would lose them
    
        if err := json.Unmarshal(d, &x); err != nil {
            return err
        }
        *t = T(x.T2)
        t.Foo = x.Foo.String()
        return nil
    }
    

    https://play.golang.org/p/BytXCeHMvt

    0 讨论(0)
提交回复
热议问题