我有以下JSON
{"a":1, "b":2, "?":1, "??":1}
我知道它有"a“和"b”字段,但我不知道其他字段的名称。所以我想用下面的类型对它进行解组:
type Foo struct {
// Known fields
A int `json:"a"`
B int `json:"b"`
// Unknown fields
X map[string]interface{} `json:???` // Rest of the fields should go here.
}
我该怎么做?
发布于 2015-10-30 22:02:45
两次解组
一种选择是解组两次:一次解组为Foo
类型的值,另一次解组为map[string]interface{}
类型的值,并删除键"a"
和"b"
type Foo struct {
A int `json:"a"`
B int `json:"b"`
X map[string]interface{} `json:"-"` // Rest of the fields should go here.
}
func main() {
s := `{"a":1, "b":2, "x":1, "y":1}`
f := Foo{}
if err := json.Unmarshal([]byte(s), &f); err != nil {
panic(err)
}
if err := json.Unmarshal([]byte(s), &f.X); err != nil {
panic(err)
}
delete(f.X, "a")
delete(f.X, "b")
fmt.Printf("%+v", f)
}
输出(在Go Playground上试用):
{A:1 B:2 X:map[x:1 y:1]}
解组一次和手动处理
另一种选择是将数据解组到map[string]interface{}
中,然后手动处理Foo.A
和Foo.B
字段:
type Foo struct {
A int `json:"a"`
B int `json:"b"`
X map[string]interface{} `json:"-"` // Rest of the fields should go here.
}
func main() {
s := `{"a":1, "b":2, "x":1, "y":1}`
f := Foo{}
if err := json.Unmarshal([]byte(s), &f.X); err != nil {
panic(err)
}
if n, ok := f.X["a"].(float64); ok {
f.A = int(n)
}
if n, ok := f.X["b"].(float64); ok {
f.B = int(n)
}
delete(f.X, "a")
delete(f.X, "b")
fmt.Printf("%+v", f)
}
输出相同(Go Playground):
{A:1 B:2 X:map[x:1 y:1]}
发布于 2015-10-30 22:02:16
它不是很好,但是您可以通过实现Unmarshaler
来实现它
type _Foo Foo
func (f *Foo) UnmarshalJSON(bs []byte) (err error) {
foo := _Foo{}
if err = json.Unmarshal(bs, &foo); err == nil {
*f = Foo(foo)
}
m := make(map[string]interface{})
if err = json.Unmarshal(bs, &m); err == nil {
delete(m, "a")
delete(m, "b")
f.X = m
}
return err
}
为了在解码时避免递归,必须使用_Foo
类型。
发布于 2017-06-01 21:23:57
最简单的方法是使用这样的接口:
var f interface{}
s := `{"a":1, "b":2, "x":1, "y":1}`
if err := json.Unmarshal([]byte(s), &f); err != nil {
panic(err)
}
https://stackoverflow.com/questions/33436730
复制相似问题