【问题标题】:How to parse/deserialize dynamic JSON如何解析/反序列化动态 JSON
【发布时间】:2015-06-03 12:29:37
【问题描述】:

场景:
考虑以下是 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
}

【问题讨论】:

标签: json go


【解决方案1】:

您可以解组为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[string]interface{}

另外请注意,我创建了一个库来轻松处理此类动态对象,这在这些情况下可能会有很大帮助:github.com/icza/dyno

【讨论】:

  • 请注意,这仅在您确定您的 json 不包含任何非字符串值时才有效。否则你必须使用map[string]interface{}{}
  • 这也假设结构只有一层深。例如,此代码不适用于第一层的文字和更深的 json。
  • @f0ster 是的,这是提问者的情况。对于任意深度,请参阅此问题:Taking a JSON string, unmarshaling it into a map, editing, and marshaling it again
  • 当我们嵌套 json 时会发生什么情况,比如 temperature 还包含其他键值。
  • @TinkalGogoi 然后解组为map[string]interface{}interface{} 类型的值。另请参阅您的评论上方的链接问题+答案。
【解决方案2】:

标准encoding/json 适用于大多数用例,但与替代解决方案相比可能会相当慢。如果您需要性能,请尝试使用fastjson。它解析任意 JSON,无需创建与 JSON 模式匹配的结构或映射。

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

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("key=%s, value=%s\n", k, v)

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

【讨论】:

  • 你应该提到你是你链接到的库的作者(fastjson)
  • 当您碰巧提到库、包等时,通常会指出您是库、包等的作者。而且它很优雅。我不认为这是一个要求。
  • 列出您是作者的好习惯,因为您可能对自己写的东西有偏见。
  • 事实上这有一个反对票大概是因为他没有说他写了fastjson是愚蠢的。我们都偏向于我们自己对 SO 的回答。他只是碰巧很久以前以一个非常受欢迎的图书馆的形式表达了他的答案......我们有一个投票系统来消除他的偏见。说您编写了一个 非商业 库是一种很好的做法,但如果要投反对票则是荒谬的。 (假设这就是原因。)
  • 我们可以检测上例中值的类型吗?
【解决方案3】:

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

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

【讨论】:

  • 我在大多数地方都看到过这种情况,但是使用空界面是一种好习惯吗?还有其他选择吗?
【解决方案4】:

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

“Gabs 是一个在 Go 中处理动态或未知 JSON 结构的小工具”

【讨论】:

  • Gabs 很棒
猜你喜欢
  • 2015-09-21
  • 2021-09-14
  • 2021-04-18
  • 2019-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 2015-11-22
相关资源
最近更新 更多