getmany返回值 gjson_golang json库gjson的使用

官方的json库, 只支持整体的序列化与反序列化. 像其它语言的库, json库都支持单个getValue/setValue这类操作.

找了下golang相关的开源json库, GJSON star数不错,支持的查询功能很丰富. 但是没有写入接口. 找了一圈也没有

找到有写入功能的json库. 能想到的只有定义类型序列化或map序列化了. 以下是正文, 翻译自项目readme:

开始

开始使用GJSON之前, 先安装Go, 然后运行go get:

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

获取值

Get查询指定路径, 通过.来区分. 比如"name.last"或者"age". 如果找到了匹配路径, 将返回结果.

package main

import "github.com/tidwall/gjson"

const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`

func main() {

value := gjson.Get(json, "name.last")

println(value.String())

}

输出结果:

Prichard

同时有 GetMany 方法批量获取值, 也有 GetBytes 方法获取字节切片.

路径解析

路径是一系列被.分隔的key拼接而成.

路径可能包含通配符'*'和'?'.

通过下标访问数组值.

通过'#'来获取值在元素中的排位或访问子路径.

.和通配符可以通过'\'来转义.

{

"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"

JSON 行

同样支持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

})

Result Type

GJSON支持json类型包括 string, number, bool, and null. 数组和对象被挡住基础类型返回.

Result 持有如下其中一种类型:

bool, for JSON booleans

float64, for JSON numbers

string, for JSON string literals

nil, for JSON null

直接访问value:

result.Type // can be String, Number, True, False, Null, or JSON

result.Str // holds the string

result.Num // holds the float64 number

result.Raw // holds the raw json

result.Index // index of raw value in original json, zero means index unknown

有各种各样的方便的函数可以获取结果:

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{}

64-bit integers

result.Int() 和 result.Uint() 返回的是64位大数字.

result.Int() int64 // -9223372036854775808 to 9223372036854775807

result.Uint() int64 // 0 to 18446744073709551615

读取嵌套数组

假如你想从下列json获取所有的lastName:

{

"programmers": [

{

"firstName": "Janet",

"lastName": "McLaughlin",

}, {

"firstName": "Elliotte",

"lastName": "Hunter",

}, {

"firstName": "Jason",

"lastName": "Harold",

}

]

}

你可以使用如下路径programmers.#.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方法允许你快速的迭代对象或数组.

key和value被传递给对象的迭代器函数.

只有value被传递给数组. 迭代器返回false将会终止迭代.

简易的Parse和Get

Parse(json)方法可以简单的分析json, result.Get(path)查询结果.

比如, 下面的几种情况都将返回相同的结果:

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

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

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

检查value是否存在

有时你想要知道值是否存在.

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

Get* 和 Parse* 方法预期json格式是正常的, 如果不正常, 将会返回不可预料的结果.

如果你读取的json来源不可预料, 那么你可以通过GJSON这么事先验证.

if !gjson.Valid(json) {

return errors.New("invalid json")

}

value := gjson.Get(json, "name.last")

反序列化到map

反序列化到map[string]interface{}:

m, ok := gjson.Parse(json).Value().(map[string]interface{})

if !ok {

// not a map

}

## 处理Bytes

如果你的JSON包含字节数组切片, 与其调用`Get(string(data), path)`, 不如调用[GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes)方法更优.

```go

var json []byte = ...

result := gjson.GetBytes(json, path)

如果你在使用gjson.GetBytes(json, path)方法, 并且你想避免从result.Raw 转换到 []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)

}

这是最好的模式, 不会为子切片重新分配内存. 这个模式使用了result.Index字段, 它直接指向了raw data所处原来json中的位置.

如果result.Raw是转换成[]byte的, result.Index将会为0.

一次获取多个值

GetMany方法可以用于同时获取多个值.

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

返回值是[]Result类型, 总是返回正传入路径个数的数量.

性能

BenchmarkGJSONGet-8 3000000 372 ns/op 0 B/op 0 allocs/op

BenchmarkGJSONUnmarshalMap-8 900000 4154 ns/op 1920 B/op 26 allocs/op

BenchmarkJSONUnmarshalMap-8 600000 9019 ns/op 3048 B/op 69 allocs/op

BenchmarkJSONDecoder-8 300000 14120 ns/op 4224 B/op 184 allocs/op

BenchmarkFFJSONLexer-8 1500000 3111 ns/op 896 B/op 8 allocs/op

BenchmarkEasyJSONLexer-8 3000000 887 ns/op 613 B/op 6 allocs/op

BenchmarkJSONParserGet-8 3000000 499 ns/op 21 B/op 0 allocs/op

BenchmarkJSONIterator-8 3000000 812 ns/op 544 B/op 9 allocs/op

使用的JSON:

{

"widget": {

"debug": "on",

"window": {

"title": "Sample Konfabulator Widget",

"name": "main_window",

"width": 500,

"height": 500

},

"image": {

"src": "Images/Sun.png",

"hOffset": 250,

"vOffset": 250,

"alignment": "center"

},

"text": {

"data": "Click Here",

"size": 36,

"style": "bold",

"vOffset": 100,

"alignment": "center",

"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"

}

}

}

每个操作都是在以下的搜索路径中进行旋转的:

widget.window.name

widget.image.hOffset

widget.text.onMouseUp

这些基准是在MacBook Pro 15" 2.8 GHz英特尔酷睿i7上运行的, 使用Go 1.8, 可以找到. here.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值