当前位置: 首页 > 工具软件 > gjson > 使用案例 >

golang中的gjson

林修真
2023-12-01

gjson包

安装使用

go get -u github.com/tidwall/gjson
const json = `{"name":[{"first":"Janet","last":"Prichard"}, {"abc": 1, "e" : 2}],"age":47}`

func main() {

   v := gjson.Get(json, "name")

   if v.String() == "" {
      fmt.Println("nil")
   } else {
      fmt.Println(v.String())
      fmt.Println(v.Type)
   }
}

简单的解析和获取

有一个Parse(json)函数可以进行简单的解析,然后result.Get(path)搜索结果。

例如,所有这些都将返回相同的结果

gjson.Parse(json).Get("name").Get("last")
gjson.Get(json, "name").Get("last")
gjson.Get(json, "name.last")

路径匹配

路径是由点分隔的一系列键。密钥可能包含特殊的通配符'*'和'?'。要访问数组值,请使用索引作为键。要获取数组中的元素数或访问子路径,请使用“#”字符。点和通配符可以使用'\'进行转义

{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"first": "Dale", "last": "Murphy", "age": 44},
    {"first": "Roger", "last": "Craig", "age": 68},
    {"first": "Jane", "last": "Murphy", "age": 47}
  ]
}

匹配结果

"name.last"          >> "Anderson"
"age"                >> 37
"children"           >> ["Sara","Alex","Jack"]
"children.#"         >> 3
"children.1"         >> "Alex"
"child*.2"           >> "Jack"
"c?ildren.0"         >> "Sara"
"fav\.movie"         >> "Deer Hunter"
"friends.#.first"    >> ["Dale","Roger","Jane"]
"friends.1.last"     >> "Craig"

反向匹配

您还可以使用#[...]或查找所有匹配项来查询第一个匹配项的数组#[...]#。查询支持==!=<<=>>=比较运算符和简单模式匹配%(像)和!%选项

friends.#[last=="Murphy"].first    >> "Dale"
friends.#[last=="Murphy"]#.first   >> ["Dale","Jane"]
friends.#[age>45]#.last            >> ["Craig","Murphy"]
friends.#[first%"D*"].last         >> "Murphy"

结果类型

GJSON支持JSON类型stringnumberbool,和null。数组和对象作为原始json类型返回。

Result类型包含以下其中一种:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON string literals
nil, for JSON null

要直接访问该值:

result.Type    //可以是String,Number,True,False,Null或JSON 
result.Str      //保存字符串 
result.Num      //保存float64数字 
result.Raw      //保存原始json 
result.Index   //原始json中原始值的索引,零表示索引未知

有各种方便的功能可以处理结果

result.Exists() bool
result.Value() interface{}
result.Int() int64
result.Uint() uint64
result.Float() float64
result.String() string
result.Bool() bool
result.Time() time.Time
result.Array() []gjson.Result
result.Map() map[string]gjson.Result
result.Get(path string) Result
result.ForEach(iterator func(key, value Result) bool)
result.Less(token Result, caseSensitive bool) bool

result.Value()函数返回一个interface{}需要类型断言的函数,它是以下Go类型之一:

result.Array()函数返回一组值。如果结果表示不存在的值,则返回空数组。如果结果不是JSON数组,则返回值将是包含一个结果的数组。

boolean >> bool 
number >> float64 
string   >> string 
null >> nil 
array >> [] interface {}
object >> map [ string ] interface {}

判断某个值是否存在:

value := gjson.Get(json, "name.last")
if !value.Exists() {
	println("no last name")
} else {
	println(value.String())
}

// Or as one step
if gjson.Get(json, "name.last").Exists() {
	println("has a last name")
}

验证json格式

if !gjson.Valid(json) {
	return errors.New("invalid json")
}
value := gjson.Get(json, "name.last")

修饰符和路径链接

版本1.2中的新功能支持修改器功能和路径链接。

修饰符是在json上执行自定义处理的路径组件。

可以使用管道字符将多个路径“链接”在一起。这对于从修改后的查询中获取结果非常有用。

例如,使用@reverse上面json文档中的内置修饰符,我们将得到children数组并反转顺序:

"children|@reverse"           >> ["Jack","Alex","Sara"]
"children|@reverse|0"         >> "Jack"

目前有三种内置修饰符:

  • @reverse:反转数组或对象的成员。
  • @ugly:从json文档中删除所有空格。
  • @pretty:使json文档更具人性化

自定义修改器

您还可以添加自定义修改器。

例如,这里我们创建一个修饰符,使整个json文档大写或小写

gjson.AddModifier("case", func(json, arg string) string {
  if arg == "upper" {
    return strings.ToUpper(json)
  }
  if arg == "lower" {
    return strings.ToLower(json)
  }
  return json
})
"children|@case:upper"           >> ["SARA","ALEX","JACK"]
"children|@case:lower|@reverse"  >> ["jack","alex","sara"]

json Lines

{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}

..#                   >> 4
..1                   >> {"name": "Alexa", "age": 34}
..3                   >> {"name": "Deloise", "age": 44}
..#.name              >> ["Gilbert","Alexa","May","Deloise"]
..#[name="May"].age   >> 57

ForEachLines函数将遍历JSON行

gjson.ForEachLine(json, func(line gjson.Result) bool{
    println(line.String())
    return true
})

获取嵌套数组值

假设您想要以下json中的所有姓氏

{
  "programmers": [
    {
      "firstName": "Janet", 
      "lastName": "McLaughlin", 
    }, {
      "firstName": "Elliotte", 
      "lastName": "Hunter", 
    }, {
      "firstName": "Jason", 
      "lastName": "Harold", 
    }
  ]
}

获取所有的lastName

result := gjson.Get(json, "programmers.#.lastName")
for _, name := range result.Array() {
	println(name.String())
}

您还可以查询数组中的对象:

name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)
println(name.String())  // prints "Elliotte"

遍历对象或数组

ForEach函数允许快速迭代对象或数组。键和值将传递给对象的迭代器函数。仅为数组传递值。false从迭代器返回将停止迭代

result := gjson.Get(json, "programmers")
result.ForEach(func(key, value gjson.Result) bool {
	println(value.String()) 
	return true // keep iterating
})

解开到map

解开到map[string]interface{}

m, ok := gjson.Parse(json).Value().(map[string]interface{})
if !ok {
	// not a map
}

使用字节

如果您的JSON包含在[]byte切片中,那么就是GetBytes函数。这是优先的Get(string(data), path)

var json []byte = ...
result := gjson.GetBytes(json, path)

如果您正在使用该gjson.GetBytes(json, path)功能并且想要避免转换result.Raw为a[]byte,则可以使用此模式

var json []byte = ...
result := gjson.GetBytes(json, path)
var raw []byte
if result.Index > 0 {
    raw = json[result.Index:result.Index+len(result.Raw)]
} else {
    raw = []byte(result.Raw)
}

这是原始json的尽力而为的无分配子切片。该方法利用result.Index字段,该字段是原始json中原始数据的位置。有可能值result.Index等于零,在这种情况下result.Raw转换为a[]byte

一次获取多个值

GetMany函数可用于同时获取多个值

results := gjson.GetMany(json, "name.first", "name.last", "age")

返回值为a[]Result,它将始终包含与输入路径完全相同的项目数

格式化

要开始使用Pretty,请安装Go并运行go get

$ go get -u github.com/tidwall/pretty
const json = `{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
    {"first": "Dale", "last": "Murphy", "age": 44},
   {"first": "Roger", "last": "Craig", "age": 68},
    {"first": "Jane", "last": "Murphy", "age": 47}
  ]
}`

func main() {

   var byteSlice []byte
   byteSlice = []byte(json)

   res := pretty.Pretty(byteSlice)
   fmt.Println(string(res))
}

复制

加上颜色

result = pretty.Color(json, nil)
 类似资料: