Encoding/Decoding JSON golang 中的多类型字段

Encoding/Decoding multi-type fields in JSON golang

我正在尝试创建一个结构,其中一个字段可以保存一些特定类型的数据,例如 intstringCustomType。我想 decode/encode 这个结构 to/from 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
  }
}

如何实现?

我可以在 MyData 上定义自己的 MarshalJSONUnmarshalJSON 并实现吗?

或者是否有定义自定义类型的方法,例如 IntOrStringOrCustom 并将 MyData 定义为

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

然后在IntOrStringOrCustom上定义MarshalJSONUnmarshalJSON

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

使用 interface{} 的问题是我将不得不在我尝试使用此数据的所有地方编写 encoding/decoding 逻辑。或者有没有一种优雅的方法可以使用 interface{}?

已更新。 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 可能方便 return 这样 class 的错误,可以定义为:

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/