json - 解码可能是字符串或对象的 JSON

标签 json go

我有一个第三方服务返回 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"`
}

如果字段值只是一个字符串,我会将其包装在类型为“Text”的 EntryVersionBlock 中,并在 Fields 映射中包含一个条目。

有什么想法可以有效地做到这一点吗?在极端情况下,我可能不得不执行数百次。

谢谢

最佳答案

您的结构与 json 的结构有点不同。 EntryVersion 中的 Fields 是对象而不是数组,因此将其设为 slice 不是您想要的。我建议您将其更改为:

type EntryVersion struct {
    Slug   string                       `json:"slug"`
    Fields map[string]EntryVersionBlock `json:"fields"`
}

EntryVersionBlock 在相应的 json 中没有 "type" 字段,它有字段名称为 "new1" 的条目,"new2" 等。所以我建议您添加第三种 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 接口(interface),检查传递给 的数据中的第一个字节UnmarshalJSON 方法,如果它是双引号,它就是一个字符串,如果它是一个大括号,它就是一个对象。像这样:

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
}

Playground :https://play.golang.org/p/IsTXI5202m

关于json - 解码可能是字符串或对象的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46753749/

相关文章:

mongodb - 使用 mgo.txn 模拟更新插入

javascript - 为传单风图格式化json

php - 在不嵌入 php 的情况下呈现表单错误

jquery $.post 第二个参数。 - json 还是查询字符串?

json - Postgres 11 Jsonpath 支持

GO Websocket 向所有客户端发送消息

java - Scala 类 Gson 库

http - 使用 curl 调用 golang jsonrpc

json - 我无法使用从请求中获取的数据创建结构

pointers - 使用值接收器 append 到具有足够容量的 slice