一尘不染

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

go

我想创建一个结构,其中一个字段可以举行一些特殊类型的,比如说的数据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解组到上述struct中MyData

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

还有这个:

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

而且这个还:

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

我该如何实现?

我可以自己定义MarshalJSONUnmarshalJSON继续MyData实现吗?

还是有一种定义自定义类型的方法,例如说IntOrStringOrCustom并定义MyData

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

然后定义MarshalJSONUnmarshalJSON继续IntOrStringOrCustom

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

使用的问题interface{}是,我将不得不在尝试使用此数据的任何地方编写编码/解码逻辑。还是有一种优雅的方式做到这一点interface{}


阅读 321

收藏
2020-07-02

共1个答案

一尘不染

更新。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/

2020-07-02