请教Golang处理Json, 处理的是 List of Json这种情况,大家有何高见?

现在Restful API 好多,有时候想要抓取些信息,整理成自己有用的,比如说 Github 的 release, 但是有些返回的不是 Json 而是 List of Json.对于这种情况,当然Python的Json库是通吃的,一点问题都没有,我用Golang重写就麻烦大了

比如举个例子:

[
    {
        "one-level": "hello",
        "two-level": {
            "aa" : "hello",
            "bb" : "world"
        }
    },
    {
        "one-level": "你好",
        "two-level": {
            "aa" : "你好",
            "bb" : "世界"
        }
    }
]

由于:

resp, err := http.Get(url)
body, err := ioutil.ReadAll(resp.Body)

最后得到的body是[]byte,我现在用 simplejson 简单的处理是这么做的:

package main

import "github.com/bitly/go-simplejson"
import "fmt"

func main() {
    bytes := []byte(`{"hello":"world"}`)
    js, _ := simplejson.NewJson(bytes)
    fmt.Println(js)

    fmt.Println(js.Get("hello").MustString())

    bytes2 := []byte(`[
    {
        "one-level": "hello",
        "two-level": {
            "aa" : "hello",
            "bb" : "world"
        }
    },
    {
        "one-level": "你好",
        "two-level": {
            "aa" : "你好",
            "bb" : "世界"
        }
    }
]`)
    js2, _ := simplejson.NewJson(bytes2)
    fmt.Println(js2.MustArray())

    arr := js2.MustArray()
    for _, item := range arr {
        m, ok := item.(map[string]interface{})
        if !ok {
            fmt.Println("Invalide data")
        }

        fmt.Println(m["one-level"])

        n, ok := m["two-level"].(map[string]interface{})
        if !ok {
            fmt.Println("Invalid data")
        }
        fmt.Println(n["bb"])
    }
}

simplejson对于纯Json的处理还是蛮方便的,但是对于这种 list of json的,感觉处理的不够优雅,各位大神有没有处理的经验,大家一般是怎么去处理这样的问题的?特别是层数比较多的情况

已邀请:

tupunco

赞同来自: DennisMao

结构复杂 看你如何理解, 去掉重复, 就不复杂了. 这种 节点多/嵌套多 的情况, 可以分多个函数, 多层 组装/填充, 简洁的代码就有了. Demo 是越简洁越好, 产品 肯定是 根据业务 来实现的.

你只是查询某几个字段, 可以写一个 struct 只包含你需要的节点就可以了. 好像有类似与 jQuery selector 的东西来做查询. 不记得是啥了, 可能就是 SimpleJSON 把.

补充, 你需要的: https://github.com/jrudolph/json-lenses https://github.com/jmoiron/jsonq

Xargin

赞同来自:

type struct Info {
    OneLevel string `json:"one-level"`
    TwoLevel struct {
       AA string
       BB string
    }
}

var arr [] Info json.Unmarshal


滴滴招聘golang工程师,简历请发至 caochunhui@didichuxing.com

bonfy

赞同来自:

@Xargin 感谢回复。这个字段比较少,把所有结构struct列清楚解包当然可以,但是如果层级很多,有些字段又多的 50+ 甚至 100+ 的,而我只是需要层级很深的比如5层以上的其中的一个字段,这么去解是不是会很麻烦。有没有更优雅的方式去实现呢?

特别我发现是 key:value,value是list的,然后list里面又有key的value是list of json的,很烦啊

tupunco

赞同来自:

你这个示范代码内的 json 数据, 按 @Xargin 的方法完全可以. 就是 var arr []info 结构, 然后 json.Unmarshal. 如果有特殊情况, 把所有特殊都列出来. 搞不懂 list of json 到底是个啥, 我印象中, json 格式就两个复杂结构:

  • Object, 型如 { Key: Value, ...} 的结构
  • Array, 型如 [ Value, ...] 的结构 Value 可以为 Object/Array + string/number/bool 等基本类型. Go 上处理 json, 本人 除了没有处理过 ArrayArray 的情况, 别的通过定义 struct 都可以解决. 如果你不知道结构如何定义, 可以试试这个站点 https://mholt.github.io/json-to-go/, 来完成 JSON Convert To Go-Struct.

Demo

[
  [
    {
      "Name": "12",
      "Age": 180
    }
  ]
]
type AutoGenerated [][]struct {
    Name string `json:"Name"`
    Age  int    `json:"Age"`
}

bonfy

赞同来自:

@tupunco 感谢回复, https://mholt.github.io/json-to-go/ 这个东西真的是赞,省了很多时间啊

我说的Json结构复杂,比如说举个例子 https://api.github.com/repos/soimort/you-get/releases

github的API,你看看那个结构,如果我只是要一个uploader 的 login name 字段,本来是很小的一个需求,但是一定要去构造一个这么复杂的Struct,心累啊,所以一直想问有没有什么优雅的方法,这是我的本意和初衷,至于表达中有不妥的地方,还请见谅

要回复问题请先登录注册