type MyObj struct {
Field1 string `json:"field_1"`
Field2 int64 `json:"field_2"`
Field3 string `json:"field_3"`
...
FieldK string `json:"field_k"`
FieldN MyInterface `json:"field_n"`
}
我的代码中有一个模型(不相关的域详细信息除外)如下所示.FieldN
字段的 idea 是支持两种类型,比如MyType1
和MyType2
.它们具有相同的CommonMethod()
,但模型非常不同,因此不是要拥有包含更多字段的父类型.
非常出人意料的是,GO无法将JSON解组为接口值.我正在try 使用定制的UnmarshalJSON()
实现,但到目前为止,它看起来真的很笨拙:
func (m *MyObj) UnmarshalJSON(data []byte) error {
out := &MyObj{}
var m map[string]json.RawMessage
if err := json.Unmarshal(data, &m); err != nil {
return err
}
if err := json.Unmarshal(m["field_1"], &out.Field1); err != nil {
return err
}
delete(m, "field_1")
if err := json.Unmarshal(m["field_2"], &out.Field2); err != nil {
return err
}
delete(m, "field_2")
if err := json.Unmarshal(m["field_3"], &out.Field3); err != nil {
return err
}
delete(m, "field_3")
... // from 3 to k-1
if err := json.Unmarshal(m["field_k"], &out.FieldK); err != nil {
return err
}
delete(m, "field_k")
var mt1 MyType1
if err := json.Unmarshal(m["field_n"], &mt1); err == nil {
s.FieldN = &mt1
return nil
}
var mt2 MyType2
if err := json.Unmarshal(m["field_n"], &mt2); err == nil {
s.FieldN = &mt2
return nil
}
return nil
}
这种方法的思想是首先解组所有的"静态"值,然后处理接口类型.然而,在我看来,它至少存在两个问题:
-
在我的例子中,future 字段的数量可能会增加,代码的重复性甚至会比现在更高
-
即使是当前版本也需要判断MAP
m
是否有关键字field_i
,否则我只会得到unexpected end of input
.这就更加麻烦了.
有没有一种更优雅的方式来做以下事情:
- 对具有静态类型的所有字段进行解组
- 处理唯一特殊的接口类型值
谢谢!
Important update:个
应该注意的是,Field1
有效地定义了FieldN
应该使用哪种具体类型.正如 comments 中指出的那样,这应该会大大简化方法,但我仍然在正确实现方面遇到了一些困难.