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

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

问题描述:

我想创建一个结构,其中一个字段可以举行一些特定类型的数据,说intstringCustomType。我想解码/编码这个结构到/从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上定义我自己的MarshalJSONUnmarshalJSON并实现此目的吗?

或者是有定义的自定义类型的方式,说IntOrStringOrCustom并定义MyData

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

然后定义上IntOrStringOrCustomMarshalJSONUnmarshalJSON?我也看过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/

+0

感谢尤金。我希望能够将解组仅限制为指定的类型。使用和接口将导致对密钥的任何类型的值进行成功解组。无论如何可以做到吗? – Shahidh

+0

@ Shahidh是的。我已更新。你能检查一下吗? –

+0

再次感谢尤金。我们已经尝试过这种方法,它工作。但问题是我们有很多结构需要进行验证。所以,为每个结构写'MarshaJSON'和'UnmarshalJSON'并不是一个可行的解决方案。可悲的是,我无法将这些方法写入'interface {}'。否则,我会写它为'TheParam'。 但是,我们发现了另一种方法,我们可以通过使用像https://github.com/asaskevich/govalidator这样的包添加'validate'标签来进行结构验证。现在试试看。将更新,如果这是前进的方式 – Shahidh