编码/解码的多类型字段golang
问题描述:
我想创建一个结构,其中一个字段可以举行一些特定类型的数据,说int
,string
和CustomType
。我想解码/编码这个结构到/从JSON。 go/golang如何实现这一目标?编码/解码的多类型字段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"`
}
比方说,我需要解组以下JSONs上述结构MyData
:
{
"name": "Hello",
"value": 32
"param": "World"
}
而这一个:
{
"name": "Hello",
"value": 32
"param": 100
}
而这其中也:
{
"name": "Hello",
"value": 32
"param": {
"custom": true
}
}
如何实现这一目标?
我可以在MyData
上定义我自己的MarshalJSON
和UnmarshalJSON
并实现此目的吗?
或者是有定义的自定义类型的方式,说IntOrStringOrCustom
并定义MyData
为
type MyData struct {
Name string `json:"name"`
Value int32 `json:"value"`
Param IntOrStringOrCustom `json:"param"`
}
然后定义上IntOrStringOrCustom
MarshalJSON
和UnmarshalJSON
?我也看过json.RawMessage
。我们能以某种方式在这里使用它吗?
使用interface{}
的问题是,我将不得不编写编码/解码逻辑,我试图使用这些数据。或者有没有一个这样做的优雅方式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
可以方便地返回错误的类,而可以被定义为:
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/
感谢尤金。我希望能够将解组仅限制为指定的类型。使用和接口将导致对密钥的任何类型的值进行成功解组。无论如何可以做到吗? – Shahidh
@ Shahidh是的。我已更新。你能检查一下吗? –
再次感谢尤金。我们已经尝试过这种方法,它工作。但问题是我们有很多结构需要进行验证。所以,为每个结构写'MarshaJSON'和'UnmarshalJSON'并不是一个可行的解决方案。可悲的是,我无法将这些方法写入'interface {}'。否则,我会写它为'TheParam'。 但是,我们发现了另一种方法,我们可以通过使用像https://github.com/asaskevich/govalidator这样的包添加'validate'标签来进行结构验证。现在试试看。将更新,如果这是前进的方式 – Shahidh