解组 JSON 具有多种值类型和任意数量的键
Unmarshall JSON with multiple value types and arbitrary number of keys
我正在尝试阅读具有以下形式的 JSON
{
string: int,
string: string,
string: MyStruct,
string: MyStruct,
...
string: MyStruct,
}
例如
{
"status": 200,
"message": "some cool text",
"coolKeyA": {
"name": "yoda",
"age": 900
},
"CoolKeyB": {
"name": "Mahalalel",
"age": 895
},
"CoolKeyC": {
"name": "Prince",
"age": 57
},
}
期望的结果是获得 map[string]MyStruct
的地图。有弹性或任意数量的“CoolKeyX”键,但其他键是静态的,例如状态和消息。
由于 JSON 中的值是不同的类型,我试图将它们放入空白 map[string]interface{}
。然后目标是遍历键并取出它们感兴趣的键并将 map[string]inferface{string: string, string: int}
的键转换为 MyStruct.
scaryAcceptAll := map[string]interface{}{}
if err = json.Unmarshal(byteArray, &scaryAcceptAll); err != nil {
log.Printf("error: %v", err)
return err
}
for k,v := range scaryAcceptAll {
if (k == "val0" ) || (k == "val1") {
continue
}
desiredMap[k] = models.MyStruct{Name: v["name"], Age: v["age"]}
}
这给了我以下错误:NonIndexableOperand: invalid operation: cannot index v (variable of type interface{})
我知道解组 JSONs 的基本思想是创建一个看起来像 json 的结构并使用它,但是因为我不知道键的确切数量或“CoolKey”键确实是(因为它是一个包含散列“000ab8f26d”的字符串)我不知道如何。我知道接口是一个包罗万象的东西,但我不确定如何从中提取我想要的数据。
一种方法是实施自定义 json.Unmarshaler
:
type Obj struct {
Status int
Message string
CoolKeys map[string]Person
}
type Person struct {
Name string
Age int
}
func (o *Obj) UnmarshalJSON(data []byte) error {
// first, unmarshal the object into a map of raw json
var m map[string]json.RawMessage
if err := json.Unmarshal(data, &m); err != nil {
return err
}
// next, unmarshal the status and message fields, and any
// other fields that don't belong to the "CoolKey" group
if err := json.Unmarshal(m["status"], &o.Status); err != nil {
return err
}
delete(m, "status") // make sure to delete it from the map
if err := json.Unmarshal(m["message"], &o.Message); err != nil {
return err
}
delete(m, "message") // make sure to delete it from the map
// finally, unmarshal the rest of the map's content
o.CoolKeys = make(map[string]Person)
for k, v := range m {
var p Person
if err := json.Unmarshal(v, &p); err != nil {
return err
}
o.CoolKeys[k] = p
}
return nil
}
我正在尝试阅读具有以下形式的 JSON
{
string: int,
string: string,
string: MyStruct,
string: MyStruct,
...
string: MyStruct,
}
例如
{
"status": 200,
"message": "some cool text",
"coolKeyA": {
"name": "yoda",
"age": 900
},
"CoolKeyB": {
"name": "Mahalalel",
"age": 895
},
"CoolKeyC": {
"name": "Prince",
"age": 57
},
}
期望的结果是获得 map[string]MyStruct
的地图。有弹性或任意数量的“CoolKeyX”键,但其他键是静态的,例如状态和消息。
由于 JSON 中的值是不同的类型,我试图将它们放入空白 map[string]interface{}
。然后目标是遍历键并取出它们感兴趣的键并将 map[string]inferface{string: string, string: int}
的键转换为 MyStruct.
scaryAcceptAll := map[string]interface{}{}
if err = json.Unmarshal(byteArray, &scaryAcceptAll); err != nil {
log.Printf("error: %v", err)
return err
}
for k,v := range scaryAcceptAll {
if (k == "val0" ) || (k == "val1") {
continue
}
desiredMap[k] = models.MyStruct{Name: v["name"], Age: v["age"]}
}
这给了我以下错误:NonIndexableOperand: invalid operation: cannot index v (variable of type interface{})
我知道解组 JSONs 的基本思想是创建一个看起来像 json 的结构并使用它,但是因为我不知道键的确切数量或“CoolKey”键确实是(因为它是一个包含散列“000ab8f26d”的字符串)我不知道如何。我知道接口是一个包罗万象的东西,但我不确定如何从中提取我想要的数据。
一种方法是实施自定义 json.Unmarshaler
:
type Obj struct {
Status int
Message string
CoolKeys map[string]Person
}
type Person struct {
Name string
Age int
}
func (o *Obj) UnmarshalJSON(data []byte) error {
// first, unmarshal the object into a map of raw json
var m map[string]json.RawMessage
if err := json.Unmarshal(data, &m); err != nil {
return err
}
// next, unmarshal the status and message fields, and any
// other fields that don't belong to the "CoolKey" group
if err := json.Unmarshal(m["status"], &o.Status); err != nil {
return err
}
delete(m, "status") // make sure to delete it from the map
if err := json.Unmarshal(m["message"], &o.Message); err != nil {
return err
}
delete(m, "message") // make sure to delete it from the map
// finally, unmarshal the rest of the map's content
o.CoolKeys = make(map[string]Person)
for k, v := range m {
var p Person
if err := json.Unmarshal(v, &p); err != nil {
return err
}
o.CoolKeys[k] = p
}
return nil
}