我正在尝试创建一个结构,其中字段可以包含几种特定类型的数据,例如int
,string
和CustomType
。我想要将此结构解码/编码为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
上定义自己的UnmarshalJSON
和MyData
并实现此目标吗?
或者有没有办法定义自定义类型,例如IntOrStringOrCustom
并将MyData
定义为
type MyData struct {
Name string `json:"name"`
Value int32 `json:"value"`
Param IntOrStringOrCustom `json:"param"`
}
然后在MarshalJSON
上定义UnmarshalJSON
和IntOrStringOrCustom
?
我也见过json.RawMessage
。我们可以在这里以某种方式使用它吗?
使用interface{}
的问题是我必须在任何地方编写编码/解码逻辑,我试图使用这些数据。或者使用interface{}
?
答案 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/