![](/img/trans.png)
[英]Type switch to []map[string]interface{} on the value of map[string]interface{}
[英]Deserialize into map[string]interface{} as a concrete map type
type Foo struct {
M map[string]interface{} `json:"m"`
}
type Bar struct {
I int `json:"i"`
}
type Bar2 struct {
S string `json:"s"`
}
func do() {
concreteFoo1 := Foo {
M: make(map[string]Bar),
}
json.Unmarshal([]byte(`{"m": {"a": { "i": 1 }}}`), &concreteFoo1)
concreteFoo2 := Foo {
M: make(map[string]Bar2),
}
json.Unmarshal([]byte(`{"m": {"a": { "s": "hello" }}}`), &concreteFoo2)
}
无法编译为:
不能在字段值中使用make(map [string] Bar)(type map [string] Bar)作为map [string] interface {}类型
不能在字段值中使用make(map [string] Bar2)(类型map [string] Bar2)作为类型map [string] interface {}
我如何才能编译和支持Foo的两个变体?
将Foo.m
更改为map[string]Bar
而不是您拥有的文件,即可对其进行编译。 要使其正常工作,您需要将Foo.m
更改为Foo.M
并将Bar.i
为Bar.I
Go JSON库不会解组或导出未导出的属性。 将大写属性映射到小写JSON元素需要使用标签。 完整的工作示例在这里 。
如果可能的Bar
类型的集合是无限的,则应使用Stud的答案中的解决方案。 解组后,您只需要执行一个类型声明即可获取map
,这比对map[string]interface{}
类型的每个值进行类型声明要好得多。
但是,如果该集合仅限于几种类型,则可以创建一个父Bar
类型,该父类型嵌入所有可能的Bar
变体列表。 万一嵌入类型的字段可能发生冲突,您仍然可以让嵌入类型实现json.Unmarshaler
接口,并对在哪里解组的内容进行一些自定义逻辑。
例如这样的事情:
type BarSet struct {
*Bar
*Bar2
}
type Bar struct {
I int `json:"i"`
}
type Bar2 struct {
S string `json:"s"`
}
https://play.golang.org/p/tJfqtnP-CX
而且,如果您想尽可能严格,则应创建单独的Foo
类型,每种类型都有其独特的M map[string]...
字段。
您可以制作通用介面
type Foo struct {
M map[string]Ibar `json:"m"`
}
type Ibar interface{}
并打开包装。
当您需要变量的特定值时,请进行类型断言。
我再次查看,认为自定义拆封器可能是一个不错的选择。
func (f *Foo) UnmarshalJSON(b []byte) error {
var tmp struct {
M map[string]json.RawMessage `json:"m"`
}
var foo = Foo{
M: make(map[string]interface{}),
}
var err error
//for key, rawValue := range
err = json.Unmarshal(b, &tmp)
if err != nil {
return err
}
for key, rawValue := range tmp.M {
var bar Bar
if json.Unmarshal(rawValue, &bar) == nil && bar.I != 0 { // custom check
foo.M[key] = bar
continue
}
var bar2 Bar2
if json.Unmarshal(rawValue, &bar2) == nil && bar2.S != "" { // custom check
foo.M[key] = bar2
continue
}
}
*f = foo
return nil
}
好处:
一处逻辑
标准通话UnmarshalJSON
可以处理几个子对象
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.