将json单个元素数组转换为字符串

时间:2017-06-28 08:10:59

标签: arrays json go decode

在Go中,我必须解析这个json:

{ 
  "response": [
    {
      "message": [
         "hello world"
      ],
      "misc": [
        {
          "timestamp": [
             "2017-06-28T05:52:39.347Z"
          ],
          "server": [
             "server-0101"
          ]
        }
      ]
    }
  ]
}

我想在Go中获取一个不包含所有不必要的数组的对象。源json在每个数组中永远不会有多个字符串。

所以我想得到的最终结果就是这个json:

{ 
  "response": {
    "message": "hello world",
    "misc": {
      "timestamp": "2017-06-28T05:52:39.347Z",
      "server": "server-0101"
    }
  }
}

或Go中的等效对象。

现在我必须使用Response[0].Misc[0].Timestamp[0]来访问看起来很奇怪的数据。

3 个答案:

答案 0 :(得分:0)

  

我想在Go中获取一个不包含所有不必要的数组的对象。

困难的方法:手工解析JSON(编写我们自己的解析器)。

明智的方法:通过包编码/ json解组到匹配JSON或某些通用interface{}的某些Go类型,然后将这些片段复制到另一个更简单的Go类型中。

答案 1 :(得分:0)

您可以通过正确定义自己的json.Marshaljson.Unmarshal来覆盖结构的MarshalJSON / UnmarshalJSON方法的默认行为。

这里有一段摘要,需要解码的结构的简化版本的代码。

type Response struct {
    Message string `json:"message"`
}

// UnmarshalJSON overrides the default behaviour for JSON unmarshal method.
func (r *Response) UnmarshalJSON(data []byte) error {
    auxResponse := &struct {
        Message []string `json:"message"`
    }{}
    if err := json.Unmarshal(data, &auxResponse); err != nil {
        return err
    }

    // Consider to add some checks on array length :)
    r.Message = auxResponse.Message[0]

    return nil
}

您可以访问完整的工作示例here

我建议你阅读这篇有趣的article about custom JSON encode/decode with golang

答案 2 :(得分:0)

创建自己的unmarshaller可能是最好的,但这是模拟你想要实现的目标的快速方法。

package main

import (
    "encoding/json"
    "fmt"
)

// JSON ...
var JSON = `{ 
  "response": [
    {
      "message": [
         "hello world"
      ],
      "misc": [
        {
          "timestamp": [
             "2017-06-28T05:52:39.347Z"
          ],
          "server": [
             "server-0101"
          ]
        }
      ]
    }
  ]
}
`

type rawObject struct {
    Response []struct {
        Message []string      `json:"message"`
        Misc    []interface{} `json:"misc"`
    } `json:"response"`
}

type clean struct {
    Message string                 `json:"message"`
    Misc    map[string]interface{} `json:"misc"`
}

func main() {
    var o rawObject
    var c clean
    // init map
    c.Misc = make(map[string]interface{})

    // unmarshall the raw data
    json.Unmarshal([]byte(JSON), &o)

    for _, res := range o.Response { // I assume there should only be one response, don't know why this is wrapped as an array
        //  assume message is not really an array
        c.Message = res.Message[0]
        // convert []interface to map[string]interface
        for _, m := range res.Misc {
            for k, v := range m.(map[string]interface{}) {
                c.Misc[k] = v
            }
        }
    }
    fmt.Printf("%+v\n", c)
}

我不喜欢这个答案是它不是非常可重复使用..因此应该制作一个函数并进行更多错误检查(创建自定义unmarshaller的一部分)。如果这是在大量生产中使用它可能会遇到一些内存问题,因为我必须创建一个原始对象来创建一个clean对象..但作为一个一个脚本它完成工作。我的clean struct不会将响应添加为类型,因为我发现它是多余的。