我有第三方服务返回JSON,其中一个字段包含数据集合。以下是它返回的结构示例。
{
"title": "Afghanistan",
"slug": "afghanistan",
"fields": {
"fieldOne": "",
"fieldTwo": {
"new1": {
"type": "contentBlock",,
"fields": {
"richTextBlick": "<p>This is the travel advice.<\/p>"
}
}
},
"fieldThree": {
"new1": {
"type": "introBlock",
"fields": {
"text": "This is a title"
"richText": "<p>This is the current travel summary for Afganistan.<\/p>"
}
},
"new2": {
"type": "contentBlock",
"fields": {
"richText": "<p>It has a second block of content!<\/p>"
}
}
},
"fieldfour": "country"
}
}
每个“字段”条目可以是字符串或其他对象。我想将这些解码为类似下面的结构。
type EntryVersion struct {
Slug string `json:"slug"`
Fields map[string][]EntryVersionBlock `json:"fields"`
}
type EntryVersionBlock struct {
Type string `json:"type"`
Fields map[string]string `json:"fields"`
}
如果字段值只是一个字符串,我会将它包装在一个EntryVersionBlock中,其类型为“Text”,并在Fields映射中包含一个条目。
任何想法如何以有效的方式做到这一点?在极端情况下,我可能要做几百次。
由于
答案 0 :(得分:4)
你的结构与json的结构略有不同。 Fields
中的EntryVersion
是一个不是数组的对象,因此将其作为切片并不是您想要的。我建议你改成它:
type EntryVersion struct {
Slug string `json:"slug"`
Fields map[string]EntryVersionBlock `json:"fields"`
}
EntryVersionBlock
在相应的json中没有"type"
字段,其中包含字段名称为"new1"
,"new2"
等的条目。所以我建议您添加第3种类型Entry
,您可以在其中解组这些字段。
type Entry struct {
Type string `json:"type"`
Fields map[string]string `json:"fields"`
}
你会更新你的EntryVersionBlock
看起来像这样:
type EntryVersionBlock struct {
Value string `json:"-"`
Fields map[string]Entry `json:"fields"`
}
要处理原始问题,您可以让EntryVersionBlock
类型实现json.Unmarshaler
接口,检查传递给UnmarshalJSON
方法的数据中的第一个字节,如果它&#39一个双引号它是一个字符串,如果它是一个卷曲的开口括号,它就是一个对象。像这样:
func (evb *EntryVersionBlock) UnmarshalJSON(data []byte) error {
switch data[0] {
case '"':
if err := json.Unmarshal(data, &evb.Value); err != nil {
return err
}
case '{':
evb.Fields = make(map[string]Entry)
if err := json.Unmarshal(data, &evb.Fields); err != nil {
return err
}
}
return nil
}
答案 1 :(得分:0)
您可以使用GJson库来解组您的JSON以进行映射,然后在此地图上进行迭代,并使用结构并根据字段类型(地图或字符串)进行所需的转换。
更新:使用此方法的示例与类似的情况 http://blog.serverbooter.com/post/parsing-nested-json-in-go/