讓 json 解析更簡單高效的 GJSON

anyanfei發表於2021-03-15

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/

更多原創文章乾貨分享,請關注公眾號
  • 讓 json 解析更簡單高效的 GJSON
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章