如何解析/反序列化动态JSON数据。

huangapple go评论87阅读模式
英文:

How to parse/deserialize dynamic JSON

问题

场景:
考虑以下JSON数据:

{
   "Bangalore_City": "35_Temperature",
   "NewYork_City": "31_Temperature",
   "Copenhagen_City": "29_Temperature"
}

如果你注意到,这个数据的结构是这样的,没有硬编码的键来指定City/Temperature,只有值。

问题: 我无法解析任何动态的JSON数据。

问题: 有人找到了解决这种JSON解析问题的方法吗?我尝试过go-simplejsongabs和默认的encoding/json,但都没有成功。

注意:
上述JSON只是一个示例。有很多应用程序正在使用当前的API,所以我不想改变数据的结构。我的意思是我不能改成以下形式:

[{
   "City_Name":"Bangalore",
   "Temperature": "35"
},...]

然后我可以定义struct

type TempData struct {
  City_Name string
  Temperature  string
}
英文:

Scenario:
<br/>Consider the following is the JSON :

{
   &quot;Bangalore_City&quot;: &quot;35_Temperature&quot;,
   &quot;NewYork_City&quot;: &quot;31_Temperature&quot;,
   &quot;Copenhagen_City&quot;: &quot;29_Temperature&quot;
}

If you notice, the data is structured in such a way that there is no hard-coded keys mentioning City/Temperature its basically just values.

Issue: I am not able to parse any JSON which is dynamic.

Question: Could anyone have found solution for this kind of JSON parsing? I tried go-simplejson, gabs & default encoding/json but no luck.

Note:
The above JSON is just for sample. And there are lot of applications which are using the current API, So I do not want to change how the data is structured. I mean I can't change to something as follows:

[{
   &quot;City_Name&quot;:&quot;Bangalore&quot;,
   &quot;Temperature&quot;: &quot;35&quot;
},...]

Then I can define struct

type TempData struct {
  City_Name string
  Temperature  string
}

答案1

得分: 64

你可以将其反序列化为map[string]string,例如:

m := map[string]string{}
err := json.Unmarshal([]byte(input), &m)
if err != nil {
    panic(err)
}
fmt.Println(m)

输出结果(换行):

map[Bangalore_City:35_Temperature NewYork_City:31_Temperature Copenhagen_City:29_Temperature]

Go Playground上尝试一下。

这样,无论键或值是什么,你都可以将所有键值对存储在一个map中,然后可以打印或遍历它们。

还要注意,尽管你的示例只包含string值,但如果值的类型不同(例如string、数字等),你可以使用interface{}作为值的类型,这样你的map将是map[string]interface{}类型。

此外,我创建了一个库,可以方便地处理这种动态对象,对于这些情况可能会有很大帮助:github.com/icza/dyno

英文:

You can unmarshal into a map[string]string for example:

m := map[string]string{}
err := json.Unmarshal([]byte(input), &amp;m)
if err != nil {
	panic(err)
}
fmt.Println(m)

Output (wrapped):

map[Bangalore_City:35_Temperature NewYork_City:31_Temperature
    Copenhagen_City:29_Temperature]

Try it on the Go Playground.

This way no matter what the keys or values are, you will have all pairs in a map which you can print or loop over.

Also note that although your example contained only string values, but if the value type is varying (e.g. string, numbers etc.), you may use interface{} for the value type, in which case your map would be of type map[string]interface{}.

Also note that I created a library to easily work with such dynamic objects which may be a great help in these cases: github.com/icza/dyno.

答案2

得分: 10

标准的encoding/json在大多数情况下都很好用,但与其他解决方案相比,它可能会比较慢。如果你需要性能,可以尝试使用fastjson。它可以解析任意的JSON,而无需创建与JSON模式匹配的结构体或映射。

请参考下面的示例代码。它遍历JSON对象的所有(key, value)对:

var p fastjson.Parser
v, err := p.Parse(input)
if err != nil {
    log.Fatal(err)
}

// 遍历顶层对象中的所有项
v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
    fmt.Printf("key=%s, value=%s\n", k, v)

    // 对于嵌套对象,再次调用Visit
    if string(k) == "nested" {
        v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
            fmt.Printf("nested key=%s, value=%s\n", k, v)
        })
    }
})
英文:

Standard encoding/json is good for the majority of use cases, but it may be quite slow comparing to alternative solutions. If you need performance, try using fastjson. It parses arbitrary JSONs without the need for creating structs or maps matching the JSON schema.

See the example code below. It iterates over all the (key, value) pairs of the JSON object:

var p fastjson.Parser
v, err := p.Parse(input)
if err != nil {
    log.Fatal(err)
}

// Visit all the items in the top object
v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
    fmt.Printf(&quot;key=%s, value=%s\n&quot;, k, v)

    // for nested objects call Visit again
    if string(k) == &quot;nested&quot; {
        v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
            fmt.Printf(&quot;nested key=%s, value=%s\n&quot;, k, v)
        })
    }
})

答案3

得分: 5

只需添加一个通用答案来解析任何有效的 JSON;var m interface{} 可以适用于所有类型。这包括了映射(OP 所要求的)、数组、字符串、数字和嵌套结构。

var m interface{}
err := json.Unmarshal([]byte(input), &m)
if err != nil {
    panic(err)
}
fmt.Println(m)
英文:

Just to add a general answer to how any valid JSON can be parsed; var m interface{} works for all types. That includes map (which OP asked for) arrays, strings, numbers and nested structures.

var m interface{}
err := json.Unmarshal([]byte(input), &amp;m)
if err != nil {
    panic(err)
}
fmt.Println(m)

答案4

得分: 2

还可以考虑使用gabs包 https://github.com/Jeffail/gabs

"Gabs是一个用于处理Go中动态或未知JSON结构的小型实用程序"

英文:

Also consider using gabs package https://github.com/Jeffail/gabs

"Gabs is a small utility for dealing with dynamic or unknown JSON structures in Go"

huangapple
  • 本文由 发表于 2015年3月30日 21:09:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/29347092.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定