酷Go推荐 让 json 解析更简单高效的 GJSON

anyanfei · 2021年03月15日 · 最后由 anyanfei 回复于 2021年03月27日 · 813 次阅读
本帖已被设为精华帖!

Golang | Gjson 库

简介 什么是 Gjson:

GJSON 是一个 Golang 包,它提供了一种快速,简单的方法来从 json 格式文档中获取值。它拥有比如单行检索,用"."符号来寻找路径,迭代和解析多行 json 的功能。

个人理解

Gjson实际上就是一个比原生 json 解析更快更简单的一种工具,对于 API 来说,我不关心这个 json 格式是否有错,我只需要关心这个 json 里面有没有我想要的数据,快速格式化成我想要的格式。

安装

GO MOD 模式下,执行:

$ go get -u github.com/tidwall/gjson 

直接获取值

我还是会由浅入深的给大家介绍这个库的使用方法,如果我们拿到了一个 json 字符串的时候应该这样做:

package main

import (
    "fmt"
    "github.com/tidwall/gjson"
)

func main() {
    exampleJsonString := `{
    "code":"000",
    "data":{
        "all_count":441353,
        "lists":[
            {
                "id":441353,
                "job_name":"经营日报-同步职位信息",
                "job_recall_time":"2021-03-13 15:05:04",
                "job_recall_content":"请求成功:great",
                "create_time":"2021-03-13 15:05:04"
            },
            {
                "id":441352,
                "job_name":"经营日报-Check张继学列表",
                "job_recall_time":"2021-03-13 15:05:00",
                "job_recall_content":"请求成功:OK",
                "create_time":"2021-03-13 15:05:00"
            }
        ]
    },
    "msg":"获取列表成功",
    "success":true
}`
    jsonCode := gjson.Get(exampleJsonString, "code")  //这个后面你可以继续跟想要的结果类型,不加的话会是json字符串的类型
    fmt.Println(jsonCode) // 结果 000
    jsonOneJobName := gjson.Get(exampleJsonString,"data.lists.#.job_name").Array() //比如我这里就希望返回是一个切片类型
    fmt.Println(jsonOneJobName) // 结果 [经营日报-同步职位信息 经营日报-Check张继学列表]
}

上面的同学开始疑问了,如果我自己写错了怎么办,或者没有那个 key 字段怎么办,没关系,你在获取到了后,加上自己想要的判断类型,再判断一次是否为空即可。

我都不需要定义任何结构体,用最简单的办法获取到我想要的内容

路径语法的快速概述:

路径语法的快速概述,以上面 json 字符串为例

路径 结果 解释
data.lists.# 2 获取当前 json 数组的长度
data.lists.1.job_name 经营日报-Check 张继学列表 获取 data 下 lists 的索引为 1 的 job_name 值
data.lists.#.job_name [经营日报 - 同步职位信息 经营日报-Check 张继学列表] 获取 data 下 lists 下所有的 job_name 值

还有一些路径通配符,比如你有模糊查询或者想在 json 取值时有判断的需求,可查看官方文档:https://github.com/tidwall/gjson

返回函数

列举一些常用的返回函数使用

package main
// ...
// ...

fmt.Println(gjson.Get(exampleJsonString,"data.lists.1.create_time").Exists()) // 查看当前路径的值是否存在 结果 true
fmt.Println(gjson.Get(exampleJsonString,"data.lists").IsArray()) //查看当前路径是否是json数组 结果 true
fmt.Println(gjson.Get(exampleJsonString,"data.lists.0").IsObject()) //查看当前路径是否是一个json对象 结果 true
gjson.Get(exampleJsonString,"data.lists.1").ForEach(func(key, value gjson.Result) bool {
        fmt.Println(value)
        return true
    }) 
//获取到路径结果后,遍历取值(其实觉得自己遍历可读性更高)
fmt.Println(gjson.Get(exampleJsonString,"data.lists.1.id").Float()) //所有标准类型都可以获取到,比如 Bool,Int,Value(这个是接口类型),Unit,String 

直接解析 bytes 类型

实际上,很多时候我们拿到的 JSON 数据都是从 API 中获得,比如从 http 请求中获得了 body,之后 ioutil.ReadAll 获得了 [] byte 类型的数据

package main

import (
    "fmt"
    "github.com/tidwall/gjson"
)

func main() {
    exampleJsonByte := []byte(`{
    "code":"000",
    "data":{
        "all_count":441353,
        "lists":[
            {
                "id":441353,
                "job_name":"经营日报-同步职位信息",
                "job_recall_time":"2021-03-13 15:05:04",
                "job_recall_content":"请求成功:great",
                "create_time":"2021-03-13 15:05:04"
            },
            {
                "id":441352,
                "job_name":"经营日报-Check张继学列表",
                "job_recall_time":"2021-03-13 15:05:00",
                "job_recall_content":"请求成功:OK",
                "create_time":"2021-03-13 15:05:00"
            }
        ]
    },
    "msg":"获取列表成功",
    "success":true
}`)
    fmt.Println(gjson.GetBytes(exampleJsonByte, "data.lists.#.job_name").Array()) //好吧,结果一样 [经营日报-同步职位信息 经营日报-Check张继学列表]
}

总结

GJSON 真的太简单了,可以说是小白 golang 解析 json 数据的必备良品,如果涉及到多人开发,需要用到同样的接口结构体,我建议还是老老实实的写结构体,毕竟数据模型的搭建是多人协同开发基础之一。

还想了解更多吗?

更多请查看:https://github.com/tidwall/gjson

欢迎加入我们 GOLANG 中国社区:https://gocn.vip/

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

以前刚入门的时候,就是用这个,现在还是老老实实的定义结构用来用。

astaxie 将本帖设为了精华贴 03月15日 06:50
4ngel 回复

为什么有这样的转变啊

DennisMao GoCN 每日新闻 (2021-03-15) 中提及了此贴 03月15日 13:27
4ngel 回复

用的不好吗

4ngel 回复

😂 怕被领导骂啊?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册