在JSON golang中编码/解码多类型字段

时间:2017-09-18 12:15:10

标签: json go encoding marshalling

我正在尝试创建一个结构,其中字段可以包含几种特定类型的数据,例如intstringCustomType。我想要将此结构解码/编码为JSON。我们怎样才能在go / golang中实现这个目标?

例如,我有一个结构用于以下定义:

type MyData struct {
  Name  string                                    `json:"name"`
  Value int32                                     `json:"value"`
  Param <can be either int, string or CustomType> `json:"param"`
}

CustomType

的位置
type CustomType struct {
  Custom bool `json:"custom"`
}

让我们说我需要将以下JSON解组为上述结构MyData

{
  "name": "Hello",
  "value": 32
  "param": "World"
}

这一个:

{
  "name": "Hello",
  "value": 32
  "param": 100
}

这个也是:

{
  "name": "Hello",
  "value": 32
  "param": {
     "custom": true
  }
}

我如何实现这一目标?

我可以在MarshalJSON上定义自己的UnmarshalJSONMyData并实现此目标吗?

或者有没有办法定义自定义类型,例如IntOrStringOrCustom并将MyData定义为

type MyData struct {
  Name  string              `json:"name"`
  Value int32               `json:"value"`
  Param IntOrStringOrCustom `json:"param"`
}

然后在MarshalJSON上定义UnmarshalJSONIntOrStringOrCustom

我也见过json.RawMessage。我们可以在这里以某种方式使用它吗?

使用interface{}的问题是我必须在任何地方编写编码/解码逻辑,我试图使用这些数据。或者使用interface{}

是否有一种优雅的方式

1 个答案:

答案 0 :(得分:2)

更新。 interface会自动编码并解码为JSON。如果您希望控制类型,可以添加特殊UnmarshalJSON并在其中执行检查:

type TheParam interface{}

type MyData struct {
    Name  string   `json:"name"`
    Value int32    `json:"value"`
    Param TheParam `json:"param"`
}

type myData MyData

func (m *MyData) UnmarshalJSON(b []byte) error {
    var mm myData
    if err := json.Unmarshal(b, &mm); err != nil {
        return err
    }
    switch mm.Param.(type) {
    case float64, string, map[string]interface{}:
        *m = MyData(mm)
        return nil
    default:
        return InvalidFieldTypeError{value: mm.Param}
    }
    return nil
}

类型InvalidFieldTypeError可能很方便返回这类错误,可以定义为:

type InvalidFieldTypeError struct {
    value interface{}
}

func (e InvalidFieldTypeError) Error() string {
    return fmt.Sprintf("Field type '%T' is not valid for MyData", e.value)
}

整个例子:https://play.golang.org/p/MuW6gwSAKi

另外,我想推荐这篇文章https://attilaolah.eu/2013/11/29/json-decoding-in-go/