【Go 推薦】快且靈活的 JSON 解析器 - Jsoniter

一、簡介

什麼是 jsoniter?

jsoniter(json-iterator)是一款快且靈活的 JSON 解析器,同時提供 Java 和 Go 兩個版本。從 dsljson 和 jsonparser 借鑑了大量代碼。

根據官網介紹:Jsoniter 的 Golang 版本可以比標準庫(encoding/json)快 6 倍之多。而且這個性能是在不使用代碼生成的前提下獲得的。

同時官網還提供了完整的 性能評測報告和 性能優化 是怎麼做的的詳盡解釋。

爲什麼用 jsoniter?

這是一個悲傷的故事,在工作的時候碰到了上游接口返回的 json 包括了兩個時間格式(時間戳和字符串),分別用 "createtime" 和 "createTime" 作爲 key。衆所周知 Go 的 json 是大小寫不敏感的,而這兩個字段類型又不同。當我同時解析這兩個字段的時候是可以的,但是當我只解析其中一個字段時就會產生 error。當時妥協選擇了兩個字段同時解析,後來又選擇了更合適的 jsoniter 來控制大小寫敏感。

二、原生 json 演示

通過下面的例子我們可以復現我當時出現的問題。只解析 createtime

package main

import (
 "encoding/json"
 "fmt"
)

const jsonText = "{\"createtime\":\"2021-04-03T17:41:48\",\"createTime\":1617442908}\n"

func main() {
 type co struct {
  Createtime string `json:"createtime"`
  //CreateTime int    `json:"createTime"`
 }
 var data co
 text := []byte(jsonText)
 err := json.Unmarshal(text, &data)
 fmt.Println(err)
 fmt.Printf("%+v", data)
}

打印結果爲:

json: cannot unmarshal number into Go struct field co.createtime of type string
{Createtime:2021-04-03T17:41:48}

只解析 createTime

type co struct {
    //Createtime string `json:"createtime"`
    CreateTime int `json:"createTime"`
}

打印結果爲:

json: cannot unmarshal string into Go struct field co.createTime of type int
{CreateTime:1617442908}

兩個都解析

type co struct {
    Createtime string `json:"createtime"`
    CreateTime int    `json:"createTime"`
}

打印結果爲:

<nil>
{Createtime:2021-04-03T17:41:48 CreateTime:1617442908}

三、jsoniter 演示

默認不區分大小寫

只解析 createtime

package main

import (
 "fmt"

 jsoniter "github.com/json-iterator/go"
)

const jsonText = "{\"createtime\":\"2021-04-03T17:41:48\",\"createTime\":1617442908}\n"

func main() {
 type co struct {
  Createtime string `json:"createtime"`
  //CreateTime int    `json:"createTime"`
 }
 var data co
 text := []byte(jsonText)
 err := jsoniter.Unmarshal(text, &data)
 fmt.Println(err)
 fmt.Printf("%+v", data)
}

打印結果爲:

main.co.Createtime: ReadString: expects " or n, but found 1, error found in #10 byte of ...|ateTime":1617442908}|..., bigger context ...|{"createtime":"2021-04-03T17:41:48","createTime":1617442908}
|...
{Createtime:}

由此我們還可以看出 json 雖然大小寫不敏感,只解析其中一個字段時也會報錯,但是可以解析正確的結果,jsoniter 默認是無法解析的。

設置爲區分大小寫

package main

import (
 "fmt"

 jsoniter "github.com/json-iterator/go"
)

const jsonText = "{\"createtime\":\"2021-04-03T17:41:48\",\"createTime\":1617442908}\n"

func main() {
 type co struct {
  Createtime string `json:"createtime"`
  //CreateTime int    `json:"createTime"`
 }
 var data co
 text := []byte(jsonText)
 json := jsoniter.Config{CaseSensitive: true}.Froze()
 err := json.Unmarshal(text, &data)
 fmt.Println(err)
 fmt.Printf("%+v", data)
}

打印結果爲:

<nil>
{Createtime:2021-04-03T17:41:48}

最後總結一下區別

l4DBX3

四、jsoniter 用法

除了像上面這種 jsoniter 自定義的特性,我們還可以將 jsoniter 替代 encoding/json 使用

import "encoding/json"
json.Marshal(&data)

替換爲

import jsoniter "github.com/json-iterator/go"

var json = jsoniter.ConfigCompatibleWithStandardLibrary
json.Marshal(&data)

import "encoding/json"
json.Unmarshal(input, &data)

替換爲

import jsoniter "github.com/json-iterator/go"

var json = jsoniter.ConfigCompatibleWithStandardLibrary
json.Unmarshal(input, &data)

參考文檔

歡迎加入我們 GOLANG 中國社區:https://gocn.vip/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/e87nDv67hG2asW8vtdsYJw