当前位置: 首页 > 知识库问答 >
问题:

如何使用 Go unmarshal 解析复杂的 JSON?

濮阳唯
2023-03-14

在<code>go</code>中,标准包编码/json公开了<code>json。Unmarshal函数解析JSON。

可以在预定义的结构中取消封送 JSON 字符串,也可以使用接口 {} 并迭代意外 JSON 数据结构的结果。

也就是说,我无法正确解析复杂的 JSON。有人可以告诉我如何实现这一目标吗?

 {
     "k1" : "v1", 
     "k2" : "v2", 
     "k3" : 10, 
     "result" : [
                 [
                 ["v4", v5, {"k11" : "v11", "k22" : "v22"}]
                 , ... , 
                 ["v4", v5, {"k33" : "v33", "k44" : "v44"}
                 ]
                 ], 
                 "v3"
                ] 
}

共有3个答案

柳业
2023-03-14

我写过JSON和Go的文章,结果发现Case int不起作用,现在需要是Case Float64,并且在现实世界的JSON中有很多嵌套。

> go version
go version go1.7.1 darwin/amd64

我还研究了Go中的JSON解码,但它对我没有太大帮助,因为我需要通过绑定将它转换成一系列对mruby的调用,并且那篇文章的作者在很大程度上对Go结构感到满意。

我花了一点时间来处理这个问题,最后的迭代转储器函数如下所示:

func dumpJSON(v interface{}, kn string) {
    iterMap := func(x map[string]interface{}, root string) {
        var knf string
        if root == "root" {
            knf = "%q:%q"
        } else {
            knf = "%s:%q"
        }
        for k, v := range x {
            dumpJSON(v, fmt.Sprintf(knf, root, k))
        }
    }

    iterSlice := func(x []interface{}, root string) {
        var knf string
        if root == "root" {
            knf = "%q:[%d]"
        } else {
            knf = "%s:[%d]"
        }
        for k, v := range x {
            dumpJSON(v, fmt.Sprintf(knf, root, k))
        }
    }

    switch vv := v.(type) {
    case string:
        fmt.Printf("%s => (string) %q\n", kn, vv)
    case bool:
        fmt.Printf("%s => (bool) %v\n", kn, vv)
    case float64:
        fmt.Printf("%s => (float64) %f\n", kn, vv)
    case map[string]interface{}:
        fmt.Printf("%s => (map[string]interface{}) ...\n", kn)
        iterMap(vv, kn)
    case []interface{}:
        fmt.Printf("%s => ([]interface{}) ...\n", kn)
        iterSlice(vv, kn)
    default:
        fmt.Printf("%s => (unknown?) ...\n", kn)
    }
}

由于 b 是一个字节片,其中 JSON 表示数组或顶层的对象,您可以像这样调用它:

var f interface{}
if err := json.Unmarshal(b, &f); err != nil {
    panic(err)
}
dumpJSON(f, "root")

希望这有所帮助,你可以试试这里的comple程序。

我建议不要自己做,除非你觉得你必须学习围棋类型的工作原理,使用reflect会让你觉得自己是宇宙的主人(就我个人而言,reflect让我抓狂)。

正如@changingrainbows在下面指出的那样,有github。com/tidwall/gjson包,它似乎包装了encoding/json<-code>,并使用反射。我可能和<code>github没什么不同。com/mitchellh/reflectwalk,它非常难使用,内部工作非常复杂。

我已经使用github.com/buger/jsonparser相当广泛地在我的一个项目中,还有github.com/json-iterator/go,我还没有尝试过,但它似乎是基于github.com/buger/jsonparser,并似乎公开了enconding/json-兼容的接口,并有func get(data[]byte, path…接口{})任何以及。为了记录,库伯斯内特项目最近切换到github.com/json-iterator/go。在我的项目中,我使用编码/json以及github.com/buger/jsonparser,我可能会切换到github.com/json-iterator/go当我有时间的时候。我会试着用更多的发现来更新这篇文章。

禹昆
2023-03-14

最近,gjson在json中提供了属性选择

k1 := gjson.Get(json, "k1")
k33 : = gjson.Get(json, "result.#.#.k33")
爱刚捷
2023-03-14

引用自JSON和Go:

在不知道此数据结构的情况下,我们可以使用Unmarshal将其解码为接口{}值:

b := []byte(`{
   "k1" : "v1", 
   "k3" : 10,
   result:["v4",12.3,{"k11" : "v11", "k22" : "v22"}]
}`)
var f interface{}
err := json.Unmarshal(b, &f)

此时,f中的Go值将是一个映射,其键为字符串,其值本身存储为空接口值:

f = map[string]interface{}{
    "k1": "v1",
    "k3":  10,
    "result": []interface{}{
       "v4",
       12.3,
       map[string]interface{}{
           "k11":"v11",
           "k22":"v22",
       },
    },
}

要访问此数据,我们可以使用类型断言访问f的底层map[string]接口{}:

m := f.(map[string]interface{})

然后,我们可以使用范围语句遍历map并使用类型开关将其值作为具体类型访问:

for k, v := range m {
    switch vv := v.(type) {
    case string:
        fmt.Println(k, "is string", vv)
    case int:
        fmt.Println(k, "is int", vv)
    case []interface{}:
        fmt.Println(k, "is an array:")
        for i, u := range vv {
            fmt.Println(i, u)
        }
    default:
        fmt.Println(k, "is of a type I don't know how to handle")
    }
}

通过这种方式,您可以处理未知的JSON数据,同时还可以享受类型安全的好处。

有关Go和JSON的更多信息可以在原始文章中找到。我稍微更改了代码片段,以更类似于问题中的JSON。

 类似资料:
  • 问题内容: 我正在寻找一种将复杂文本文件解析为pandas DataFrame的简单方法。下面是一个示例文件,我希望解析后的结果是什么样,以及我当前的方法。 有什么方法可以使其更简洁/更快/更pythonic /更易读? 我也把这个问题放在了Code Review上 。 我最终写了一篇博客文章向初学者解释。 这是一个示例文件: 这是我希望解析后的结果看起来像什么: 这是我目前解析的方式: 问题答案

  • 我收到了一个包含字符串和元组元素组合的CSV文件,但找不到正确解析它的方法。我错过了什么明显的东西吗? csvfile 第一行是标题,第二行开始数据 产量: csv.reader解析每行不同,因为结构复杂,嵌入了花括号元素。 ...但是我希望每行有20个元素。

  • 我从一个复杂的json中获取空数据,这里是json。当我试图解析它时,我得到了null。请看一看。 我已生成模型类:https://javiercbk.github.io/json_to_dart/ 生成模型类后,创建一个新的类名ModelClass。 另一个类名为APiResponse并编写代码:这个类获取api响应并返回响应:APiResponse。fromJson(jsonDecode(re

  • 问题内容: 是否可以对JSON对象执行复杂的查询?我愿意接受JavaScript或jQuery解决方案,越轻松越好。我正在构想某种类似于LINQ或SQL的功能编程语言。 我不希望其他任何第三方库或附加组件。 更新 从早期答案的外观来看,将需要一个附加组件。在这种情况下,我更喜欢不需要安装过程的加载项。随软件发布一起部署的东西(如jQuery)很好(例如* .js文件集)。 问题答案: 签出:是否有

  • 问题内容: 我有一个很长的JSON与Gson一起解析,但是为了简洁起见,我将其修剪为以下示例: 从SO和其他几个地方,我发现我需要定义一个顶级容器,例如下面的容器,但我不知道如何完成其​​定义 然后每堂课 我正在尝试解析它,这是到目前为止我编写的代码: JSON字符串存储在名为response的变量中 我的最终要求是of,并且关联。 问题答案: 第一个问题 :您的需求是: 它不必是静态的。 第二个