代码之家  ›  专栏  ›  技术社区  ›  Tigraine

JSON将整数字段解组为字符串

  •  6
  • Tigraine  · 技术社区  · 7 年前

    我正在努力将整数反序列化为字符串结构字段。 用户可以提供文本,但有些用户只分配整数。

    type Test struct {
      Foo string
    }
    

    有时我会得到一个有效的JSON值,但不会反序列化到结构中,因为Foo字段是整数而不是字符串:

    { "foo": "1" } // works
    { "foo": 1 } // doesn't
    

    json。解组将出现以下错误: json: cannot unmarshal number into Go struct field test.Foo of type string

    https://play.golang.org/p/4Qau3umaVm

    现在,在我迄今为止使用过的所有其他JSON库(在其他语言中)中,如果目标字段是一个字符串,并且您得到一个整数,则反序列化器通常只会将int包装在一个字符串中,然后使用它。这能在围棋中实现吗?

    json.Unmarshal 对此不敏感-另一种解决方案是将Foo定义为 interface{} 这不必要地使我的代码与类型断言等复杂化。。

    有什么办法吗?我基本上需要的是 json:",string"

    2 回复  |  直到 7 年前
        1
  •  6
  •   mkopriva    7 年前

    要处理大型结构,可以使用嵌入。

    更新为不丢弃以前可能设置的字段值。

    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

        2
  •  3
  •   Rohman HM mohdajami    3 年前

    您可以通过实现 json.Unmarshaler 界面

    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