在Go中解组嵌套的自定义同类型JSON

时间:2018-11-17 13:07:38

标签: json go recursion

给出以下JSON

{
   "some": "value"
   "nested": {
     "some": "diffvalue",
     "nested": {
        "some": "innervalue"
     }
   }
}

大致翻译为以下结构:

type Envelope struct {
    some     string         `json:"some"`
    nested   InnerEnvelope  `json:"nested"`
}

其中InnerEnvelope是:type InnerEnvelope map[string]interface{}

由于原始JSON的递归类型性质,运行简单的json.Unmarshal([]byte value, &target)在这里无济于事。

我不知道内部映射将在多大深度和在哪个键下存在,因此我无法预先声明类型。

这个想法是,使用map[string]interface{}作为类型还不够好,因为我需要InnerEnvelope中的值进行某种转换和键入。细节并不重要,但是图像,我需要将布尔类型的NestedEnvelope内的每个值都强制转换为字符串,说“ true”或“ false”,而不是具有实际的bool类型。 / p>

我转向UnmarshalJSON界面来解决此问题。我可以像这样轻松地在最高级别做到这一点:

func (m *Envelope) UnmarshalJSON(b []byte) error {
    var stuff noBoolMap
    if err := json.Unmarshal(b, &stuff); err != nil {
        return err
    }
    for key, value := range stuff {
        switch value.(type) {

        case bool:
            stuff[key] = strconv.FormatBool(value.(bool))
        }
    }
    return nil
}

但是由于内部json.Unmarshal已经具有解析为map[string]interface{}的内部映射,所以我仍然需要再次遍历内部映射,将它们转换为适当的类型并执行我的值转换。 / p>

所以我的问题是:在这种情况下,Go中采用哪种方式进行处理,最好是单次通过?

上面的JSON示例的预期结果将是:

Envelope {
     some: string
     nested: InnerEnvelope {
       some: string {
       nested: InnerEnvelope {
         some: string
       }
     }
  }

1 个答案:

答案 0 :(得分:0)

给出您的json,您可以执行以下操作:

type Envelope struct {
    some     string         `json:"some"`
    nested   json.RawMessage  `json:"nested"`
}

json.RawMessage是一个相当隐蔽的瑰宝,而且似乎有更多人喜欢map [string] interface {}。

使用json.RawMessage将导致嵌套的json由此RawMessage表示,然后您可以将其作为普通json再次处理(将其解组为Envelope)。

这比map [string] interface {}方法更优雅。