我想创建一个结构,其中一个字段可以举行一些特殊类型的,比如说的数据int,string和CustomType。我想将此结构从JSON解码/编码。我们如何在go / golang中实现这一目标?
int
string
CustomType
例如,我具有以下定义的结构:
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:
MyData
{ "name": "Hello", "value": 32 "param": "World" }
还有这个:
{ "name": "Hello", "value": 32 "param": 100 }
而且这个还:
{ "name": "Hello", "value": 32 "param": { "custom": true } }
我该如何实现?
我可以自己定义MarshalJSON并UnmarshalJSON继续MyData实现吗?
MarshalJSON
UnmarshalJSON
还是有一种定义自定义类型的方法,例如说IntOrStringOrCustom并定义MyData为
IntOrStringOrCustom
type MyData struct { Name string `json:"name"` Value int32 `json:"value"` Param IntOrStringOrCustom `json:"param"` }
然后定义MarshalJSON并UnmarshalJSON继续IntOrStringOrCustom?
我也看到过json.RawMessage。我们可以在这里以某种方式使用它吗?
json.RawMessage
使用的问题interface{}是,我将不得不在尝试使用此数据的任何地方编写编码/解码逻辑。还是有一种优雅的方式做到这一点interface{}?
interface{}
更新。interface会自动很好地编码和解码为JSON。如果您希望控制类型,则可以添加特殊字符UnmarshalJSON并在其中进行检查:
interface
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可能方便返回此类错误,并且可以将其定义为:
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/