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

Arrays 将json单元素数组转换为字符串,arrays,json,go,decode,Arrays,Json,Go,Decode,在Go中,我必须解析这个json: { "response": [ { "message": [ "hello world" ], "misc": [ { "timestamp": [ "2017-06-28T05:52:39.347Z" ], "server": [ "server-0101"

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

{ 
  "response": [
    {
      "message": [
         "hello world"
      ],
      "misc": [
        {
          "timestamp": [
             "2017-06-28T05:52:39.347Z"
          ],
          "server": [
             "server-0101"
          ]
        }
      ]
    }
  ]
}
{ 
  "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"
          ]
        }
      ]
    }
  ]
}
{ 
  "response": {
    "message": "hello world",
    "misc": {
      "timestamp": "2017-06-28T05:52:39.347Z",
      "server": "server-0101"
    }
  }
}
或Go中的等效对象

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

我想在Go中获得一个对象,它不包含所有不必要的数组,只包含一个字符串

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


明智的方法是:通过包编码/json将其解组为与json匹配的某种Go类型,或者解组为某种通用的
接口{}
,然后将片段复制为不同的、更简单的Go类型。

您可以覆盖结构的
json.Marshal
/
json.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
}
您可以访问完整的工作示例


我建议您阅读这篇有趣的文章。

创建您自己的解组器可能是最好的,但这是一种模拟您想要实现的目标的快速方法

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)
}
我不喜欢这个答案的原因是它不太可重用。因此,可能应该创建一个函数并进行更多的错误检查(创建自定义解组器的一部分)。如果在大批量生产中使用,它可能会遇到一些内存问题,因为我必须创建一个原始对象来创建
clean
对象。。但作为一个一次性脚本,它完成了任务。我认为我的clean结构没有将响应作为类型添加,因为我发现它是冗余的