编码/解码JSON golang中的多类型字段
我正在尝试创建一个结构,其中一个字段可以保存一些特殊类型的数据,例如int
,string
和CustomType
.我想将此结构从JSON解码/编码.我们如何在go/golang中实现这一目标?
I am trying to create a struct where a field can hold data of a few particular types, say int
, string
and a CustomType
. I want to decode/encode this struct to/from JSON. How can we achieve this in go/golang?
例如,我具有以下定义的结构:
For example, I have a struct for the following definition:
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
:
Let's say I need to unmarshal the following JSONs to the above struct MyData
:
{
"name": "Hello",
"value": 32
"param": "World"
}
还有一个:
{
"name": "Hello",
"value": 32
"param": 100
}
这也是:
{
"name": "Hello",
"value": 32
"param": {
"custom": true
}
}
我该如何实现?
我可以在MyData
上定义自己的MarshalJSON
和UnmarshalJSON
并实现吗?
Can I define my own MarshalJSON
and UnmarshalJSON
on MyData
and achieve this?
或者是否可以定义自定义类型,例如IntOrStringOrCustom
并将MyData
定义为
Or is there a way of defining a custom type, say IntOrStringOrCustom
and define MyData
as
type MyData struct {
Name string `json:"name"`
Value int32 `json:"value"`
Param IntOrStringOrCustom `json:"param"`
}
,然后在IntOrStringOrCustom
上定义MarshalJSON
和UnmarshalJSON
?
我也看过json.RawMessage
.我们可以在这里以某种方式使用它吗?
I have also seen json.RawMessage
. Can we use it somehow here?
使用interface{}
的问题是,我将不得不在尝试使用此数据的任何地方编写编码/解码逻辑.还是用interface{}
做到这一点的优雅方法?
Issue with using interface{}
is that I will have to write the encoding/decoding logic everywhere, where I am trying to use this data. Or is there an elegant way of doing this with interface{}
?
已更新. interface
会自动很好地编码和解码为JSON.如果希望控制类型,则可以添加特殊的UnmarshalJSON
并在其中进行检查:
UPDATED. interface
gets encoded and decoded to JSON well automatically. If you wish to control types, you may add special UnmarshalJSON
and perform checks in it:
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
may be convenient to return such class of errors and can be defined as:
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/