在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]
来访问看起来很奇怪的数据。
答案 0 :(得分:0)
我想在Go中获取一个不包含所有不必要的数组的对象。
困难的方法:手工解析JSON(编写我们自己的解析器)。
明智的方法:通过包编码/ json解组到匹配JSON或某些通用interface{}
的某些Go类型,然后将这些片段复制到另一个更简单的Go类型中。
答案 1 :(得分:0)
您可以通过正确定义自己的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
}
您可以访问完整的工作示例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不会将响应添加为类型,因为我发现它是多余的。