forked from mirror/gjson
repo fixes
This commit is contained in:
parent
e14b8d3708
commit
7ca23b5734
14
README.md
14
README.md
|
@ -3,7 +3,7 @@
|
||||||
src="logo.png"
|
src="logo.png"
|
||||||
width="240" height="78" border="0" alt="GJSON">
|
width="240" height="78" border="0" alt="GJSON">
|
||||||
<br>
|
<br>
|
||||||
<a href="https://godoc.org/github.com/tidwall/gjson"><img src="https://img.shields.io/badge/api-reference-blue.svg?style=flat-square" alt="GoDoc"></a>
|
<a href="https://godoc.org/git.internal/re/gjson"><img src="https://img.shields.io/badge/api-reference-blue.svg?style=flat-square" alt="GoDoc"></a>
|
||||||
<a href="https://tidwall.com/gjson-play"><img src="https://img.shields.io/badge/%F0%9F%8F%90-playground-9900cc.svg?style=flat-square" alt="GJSON Playground"></a>
|
<a href="https://tidwall.com/gjson-play"><img src="https://img.shields.io/badge/%F0%9F%8F%90-playground-9900cc.svg?style=flat-square" alt="GJSON Playground"></a>
|
||||||
<a href="SYNTAX.md"><img src="https://img.shields.io/badge/{}-syntax-33aa33.svg?style=flat-square" alt="GJSON Syntax"></a>
|
<a href="SYNTAX.md"><img src="https://img.shields.io/badge/{}-syntax-33aa33.svg?style=flat-square" alt="GJSON Syntax"></a>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and
|
||||||
|
|
||||||
This README is a quick overview of how to use GJSON, for more information check out [GJSON Syntax](SYNTAX.md).
|
This README is a quick overview of how to use GJSON, for more information check out [GJSON Syntax](SYNTAX.md).
|
||||||
|
|
||||||
GJSON is also available for [Python](https://github.com/volans-/gjson-py) and [Rust](https://github.com/tidwall/gjson.rs)
|
GJSON is also available for [Python](https://github.com/volans-/gjson-py) and [Rust](https://git.internal/re/gjson.rs)
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
===============
|
===============
|
||||||
|
@ -28,7 +28,7 @@ Getting Started
|
||||||
To start using GJSON, install Go and run `go get`:
|
To start using GJSON, install Go and run `go get`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go get -u github.com/tidwall/gjson
|
$ go get -u git.internal/re/gjson
|
||||||
```
|
```
|
||||||
|
|
||||||
This will retrieve the library.
|
This will retrieve the library.
|
||||||
|
@ -39,7 +39,7 @@ Get searches json for the specified path. A path is in dot syntax, such as "name
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/tidwall/gjson"
|
import "git.internal/re/gjson"
|
||||||
|
|
||||||
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
|
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ There are currently the following built-in modifiers:
|
||||||
- `@values`: Returns an array of values for an object.
|
- `@values`: Returns an array of values for an object.
|
||||||
- `@tostr`: Converts json to a string. Wraps a json string.
|
- `@tostr`: Converts json to a string. Wraps a json string.
|
||||||
- `@fromstr`: Converts a string from json. Unwraps a json string.
|
- `@fromstr`: Converts a string from json. Unwraps a json string.
|
||||||
- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
|
- `@group`: Groups arrays of objects. See [e4fc67c](https://git.internal/re/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
|
||||||
|
|
||||||
### Modifier arguments
|
### Modifier arguments
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ if !ok {
|
||||||
|
|
||||||
## Working with Bytes
|
## Working with Bytes
|
||||||
|
|
||||||
If your JSON is contained in a `[]byte` slice, there's the [GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes) function. This is preferred over `Get(string(data), path)`.
|
If your JSON is contained in a `[]byte` slice, there's the [GetBytes](https://godoc.org/git.internal/re/gjson#GetBytes) function. This is preferred over `Get(string(data), path)`.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
var json []byte = ...
|
var json []byte = ...
|
||||||
|
@ -494,4 +494,4 @@ widget.image.hOffset
|
||||||
widget.text.onMouseUp
|
widget.text.onMouseUp
|
||||||
```
|
```
|
||||||
|
|
||||||
*These benchmarks were run on a MacBook Pro 16" 2.4 GHz Intel Core i9 using Go 1.17 and can be found [here](https://github.com/tidwall/gjson-benchmarks).*
|
*These benchmarks were run on a MacBook Pro 16" 2.4 GHz Intel Core i9 using Go 1.17 and can be found [here](https://git.internal/re/gjson-benchmarks).*
|
||||||
|
|
|
@ -15,7 +15,7 @@ This document is designed to explain the structure of a GJSON Path through examp
|
||||||
- [Multipaths](#multipaths)
|
- [Multipaths](#multipaths)
|
||||||
- [Literals](#literals)
|
- [Literals](#literals)
|
||||||
|
|
||||||
The definitive implemenation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
|
The definitive implemenation is [git.internal/re/gjson](https://git.internal/re/gjson).
|
||||||
Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online.
|
Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online.
|
||||||
|
|
||||||
## Path structure
|
## Path structure
|
||||||
|
@ -240,7 +240,7 @@ There are currently the following built-in modifiers:
|
||||||
- `@values`: Returns an array of values for an object.
|
- `@values`: Returns an array of values for an object.
|
||||||
- `@tostr`: Converts json to a string. Wraps a json string.
|
- `@tostr`: Converts json to a string. Wraps a json string.
|
||||||
- `@fromstr`: Converts a string from json. Unwraps a json string.
|
- `@fromstr`: Converts a string from json. Unwraps a json string.
|
||||||
- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
|
- `@group`: Groups arrays of objects. See [e4fc67c](https://git.internal/re/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
|
||||||
|
|
||||||
#### Modifier arguments
|
#### Modifier arguments
|
||||||
|
|
||||||
|
@ -339,4 +339,4 @@ This results in
|
||||||
{"first":"Tom","age":37,"company":"Happysoft","employed":true}
|
{"first":"Tom","age":37,"company":"Happysoft","employed":true}
|
||||||
```
|
```
|
||||||
|
|
||||||
*See issue [#249](https://github.com/tidwall/gjson/issues/249) for additional context on JSON Literals.*
|
*See issue [#249](https://git.internal/re/gjson/issues/249) for additional context on JSON Literals.*
|
||||||
|
|
142
gjson_test.go
142
gjson_test.go
|
@ -199,7 +199,6 @@ func TestPath(t *testing.T) {
|
||||||
get("loggy.programmers.2.email")
|
get("loggy.programmers.2.email")
|
||||||
get("lastly.end\\.\\.\\.ing")
|
get("lastly.end\\.\\.\\.ing")
|
||||||
get("lastly.yay")
|
get("lastly.yay")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeResult(t *testing.T) {
|
func TestTimeResult(t *testing.T) {
|
||||||
|
@ -216,8 +215,10 @@ func TestParseAny(t *testing.T) {
|
||||||
|
|
||||||
func TestManyVariousPathCounts(t *testing.T) {
|
func TestManyVariousPathCounts(t *testing.T) {
|
||||||
json := `{"a":"a","b":"b","c":"c"}`
|
json := `{"a":"a","b":"b","c":"c"}`
|
||||||
counts := []int{3, 4, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127,
|
counts := []int{
|
||||||
128, 129, 255, 256, 257, 511, 512, 513}
|
3, 4, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127,
|
||||||
|
128, 129, 255, 256, 257, 511, 512, 513,
|
||||||
|
}
|
||||||
paths := []string{"a", "b", "c"}
|
paths := []string{"a", "b", "c"}
|
||||||
expects := []string{"a", "b", "c"}
|
expects := []string{"a", "b", "c"}
|
||||||
for _, count := range counts {
|
for _, count := range counts {
|
||||||
|
@ -238,6 +239,7 @@ func TestManyVariousPathCounts(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestManyRecursion(t *testing.T) {
|
func TestManyRecursion(t *testing.T) {
|
||||||
var json string
|
var json string
|
||||||
var path string
|
var path string
|
||||||
|
@ -252,6 +254,7 @@ func TestManyRecursion(t *testing.T) {
|
||||||
path = path[1:]
|
path = path[1:]
|
||||||
assert(t, GetMany(json, path)[0].String() == "b")
|
assert(t, GetMany(json, path)[0].String() == "b")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestByteSafety(t *testing.T) {
|
func TestByteSafety(t *testing.T) {
|
||||||
jsonb := []byte(`{"name":"Janet","age":38}`)
|
jsonb := []byte(`{"name":"Janet","age":38}`)
|
||||||
mtok := GetBytes(jsonb, "name")
|
mtok := GetBytes(jsonb, "name")
|
||||||
|
@ -348,6 +351,7 @@ func TestPlus53BitInts(t *testing.T) {
|
||||||
// flip the number to the negative sign.
|
// flip the number to the negative sign.
|
||||||
assert(t, Get(json, "overflow_int64").Int() == -9223372036854775808)
|
assert(t, Get(json, "overflow_int64").Int() == -9223372036854775808)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue38(t *testing.T) {
|
func TestIssue38(t *testing.T) {
|
||||||
// These should not fail, even though the unicode is invalid.
|
// These should not fail, even though the unicode is invalid.
|
||||||
Get(`["S3O PEDRO DO BUTI\udf93"]`, "0")
|
Get(`["S3O PEDRO DO BUTI\udf93"]`, "0")
|
||||||
|
@ -359,6 +363,7 @@ func TestIssue38(t *testing.T) {
|
||||||
Get(`["S3O PEDRO DO BUTI\udf93\u1345"]`, "0")
|
Get(`["S3O PEDRO DO BUTI\udf93\u1345"]`, "0")
|
||||||
Get(`["S3O PEDRO DO BUTI\udf93\u1345asd"]`, "0")
|
Get(`["S3O PEDRO DO BUTI\udf93\u1345asd"]`, "0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTypes(t *testing.T) {
|
func TestTypes(t *testing.T) {
|
||||||
assert(t, (Result{Type: String}).Type.String() == "String")
|
assert(t, (Result{Type: String}).Type.String() == "String")
|
||||||
assert(t, (Result{Type: Number}).Type.String() == "Number")
|
assert(t, (Result{Type: Number}).Type.String() == "Number")
|
||||||
|
@ -404,6 +409,7 @@ func TestTypes(t *testing.T) {
|
||||||
assert(t, (Result{Type: False}).Float() == 0)
|
assert(t, (Result{Type: False}).Float() == 0)
|
||||||
assert(t, (Result{Type: Number, Num: 1}).Float() == 1)
|
assert(t, (Result{Type: Number, Num: 1}).Float() == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForEach(t *testing.T) {
|
func TestForEach(t *testing.T) {
|
||||||
Result{}.ForEach(nil)
|
Result{}.ForEach(nil)
|
||||||
Result{Type: String, Str: "Hello"}.ForEach(func(_, value Result) bool {
|
Result{Type: String, Str: "Hello"}.ForEach(func(_, value Result) bool {
|
||||||
|
@ -423,6 +429,7 @@ func TestForEach(t *testing.T) {
|
||||||
ParseBytes([]byte(`{"bad`)).ForEach(nil)
|
ParseBytes([]byte(`{"bad`)).ForEach(nil)
|
||||||
ParseBytes([]byte(`{"ok":"bad`)).ForEach(nil)
|
ParseBytes([]byte(`{"ok":"bad`)).ForEach(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
assert(t, len(ParseBytes([]byte(`"asdf"`)).Map()) == 0)
|
assert(t, len(ParseBytes([]byte(`"asdf"`)).Map()) == 0)
|
||||||
assert(t, ParseBytes([]byte(`{"asdf":"ghjk"`)).Map()["asdf"].String() ==
|
assert(t, ParseBytes([]byte(`{"asdf":"ghjk"`)).Map()["asdf"].String() ==
|
||||||
|
@ -431,6 +438,7 @@ func TestMap(t *testing.T) {
|
||||||
assert(t, Result{Type: JSON, Raw: "**invalid**"}.Value() == nil)
|
assert(t, Result{Type: JSON, Raw: "**invalid**"}.Value() == nil)
|
||||||
assert(t, Result{Type: JSON, Raw: "{"}.Map() != nil)
|
assert(t, Result{Type: JSON, Raw: "{"}.Map() != nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasic1(t *testing.T) {
|
func TestBasic1(t *testing.T) {
|
||||||
mtok := get(basicJSON, `loggy.programmers`)
|
mtok := get(basicJSON, `loggy.programmers`)
|
||||||
var count int
|
var count int
|
||||||
|
@ -474,6 +482,7 @@ func TestBasic1(t *testing.T) {
|
||||||
t.Fatalf("expected %v, got %v", 3, count)
|
t.Fatalf("expected %v, got %v", 3, count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasic2(t *testing.T) {
|
func TestBasic2(t *testing.T) {
|
||||||
mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`)
|
mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`)
|
||||||
if mtok.String() != "1002.3" {
|
if mtok.String() != "1002.3" {
|
||||||
|
@ -509,6 +518,7 @@ func TestBasic2(t *testing.T) {
|
||||||
mtok.Map()["programmers"].Array()[1].Map()["firstName"].Str)
|
mtok.Map()["programmers"].Array()[1].Map()["firstName"].Str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasic3(t *testing.T) {
|
func TestBasic3(t *testing.T) {
|
||||||
var mtok Result
|
var mtok Result
|
||||||
if Parse(basicJSON).Get("loggy.programmers").Get("1").
|
if Parse(basicJSON).Get("loggy.programmers").Get("1").
|
||||||
|
@ -549,6 +559,7 @@ func TestBasic3(t *testing.T) {
|
||||||
t.Fatalf("expected 0, got %v", len(mtok.Array()))
|
t.Fatalf("expected 0, got %v", len(mtok.Array()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasic4(t *testing.T) {
|
func TestBasic4(t *testing.T) {
|
||||||
if get(basicJSON, "items.3.tags.#").Num != 3 {
|
if get(basicJSON, "items.3.tags.#").Num != 3 {
|
||||||
t.Fatalf("expected 3, got %v", get(basicJSON, "items.3.tags.#").Num)
|
t.Fatalf("expected 3, got %v", get(basicJSON, "items.3.tags.#").Num)
|
||||||
|
@ -593,6 +604,7 @@ func TestBasic4(t *testing.T) {
|
||||||
t.Fatal("should be nil")
|
t.Fatal("should be nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasic5(t *testing.T) {
|
func TestBasic5(t *testing.T) {
|
||||||
token := get(basicJSON, "age")
|
token := get(basicJSON, "age")
|
||||||
if token.String() != "100" {
|
if token.String() != "100" {
|
||||||
|
@ -630,8 +642,9 @@ func TestBasic5(t *testing.T) {
|
||||||
t.Fatalf("expecting %v, got %v", "Jason", fn)
|
t.Fatalf("expecting %v, got %v", "Jason", fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnicode(t *testing.T) {
|
func TestUnicode(t *testing.T) {
|
||||||
var json = `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
|
json := `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
|
||||||
if Get(json, "的情况下解.key").Num != 1 {
|
if Get(json, "的情况下解.key").Num != 1 {
|
||||||
t.Fatal("fail")
|
t.Fatal("fail")
|
||||||
}
|
}
|
||||||
|
@ -659,11 +672,13 @@ func TestUnescape(t *testing.T) {
|
||||||
unescape(string([]byte{'\\', '\\', 0}))
|
unescape(string([]byte{'\\', '\\', 0}))
|
||||||
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
|
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func assert(t testing.TB, cond bool) {
|
func assert(t testing.TB, cond bool) {
|
||||||
if !cond {
|
if !cond {
|
||||||
panic("assert failed")
|
panic("assert failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLess(t *testing.T) {
|
func TestLess(t *testing.T) {
|
||||||
assert(t, !Result{Type: Null}.Less(Result{Type: Null}, true))
|
assert(t, !Result{Type: Null}.Less(Result{Type: Null}, true))
|
||||||
assert(t, Result{Type: Null}.Less(Result{Type: False}, true))
|
assert(t, Result{Type: Null}.Less(Result{Type: False}, true))
|
||||||
|
@ -673,18 +688,30 @@ func TestLess(t *testing.T) {
|
||||||
assert(t, Result{Type: Null}.Less(Result{Type: String}, true))
|
assert(t, Result{Type: Null}.Less(Result{Type: String}, true))
|
||||||
assert(t, !Result{Type: False}.Less(Result{Type: Null}, true))
|
assert(t, !Result{Type: False}.Less(Result{Type: Null}, true))
|
||||||
assert(t, Result{Type: False}.Less(Result{Type: True}, true))
|
assert(t, Result{Type: False}.Less(Result{Type: True}, true))
|
||||||
assert(t, Result{Type: String, Str: "abc"}.Less(Result{Type: String,
|
assert(t, Result{Type: String, Str: "abc"}.Less(Result{
|
||||||
Str: "bcd"}, true))
|
Type: String,
|
||||||
assert(t, Result{Type: String, Str: "ABC"}.Less(Result{Type: String,
|
Str: "bcd",
|
||||||
Str: "abc"}, true))
|
}, true))
|
||||||
assert(t, !Result{Type: String, Str: "ABC"}.Less(Result{Type: String,
|
assert(t, Result{Type: String, Str: "ABC"}.Less(Result{
|
||||||
Str: "abc"}, false))
|
Type: String,
|
||||||
assert(t, Result{Type: Number, Num: 123}.Less(Result{Type: Number,
|
Str: "abc",
|
||||||
Num: 456}, true))
|
}, true))
|
||||||
assert(t, !Result{Type: Number, Num: 456}.Less(Result{Type: Number,
|
assert(t, !Result{Type: String, Str: "ABC"}.Less(Result{
|
||||||
Num: 123}, true))
|
Type: String,
|
||||||
assert(t, !Result{Type: Number, Num: 456}.Less(Result{Type: Number,
|
Str: "abc",
|
||||||
Num: 456}, true))
|
}, false))
|
||||||
|
assert(t, Result{Type: Number, Num: 123}.Less(Result{
|
||||||
|
Type: Number,
|
||||||
|
Num: 456,
|
||||||
|
}, true))
|
||||||
|
assert(t, !Result{Type: Number, Num: 456}.Less(Result{
|
||||||
|
Type: Number,
|
||||||
|
Num: 123,
|
||||||
|
}, true))
|
||||||
|
assert(t, !Result{Type: Number, Num: 456}.Less(Result{
|
||||||
|
Type: Number,
|
||||||
|
Num: 456,
|
||||||
|
}, true))
|
||||||
assert(t, stringLessInsensitive("abcde", "BBCDE"))
|
assert(t, stringLessInsensitive("abcde", "BBCDE"))
|
||||||
assert(t, stringLessInsensitive("abcde", "bBCDE"))
|
assert(t, stringLessInsensitive("abcde", "bBCDE"))
|
||||||
assert(t, stringLessInsensitive("Abcde", "BBCDE"))
|
assert(t, stringLessInsensitive("Abcde", "BBCDE"))
|
||||||
|
@ -776,7 +803,7 @@ var exampleJSON = `{
|
||||||
}`
|
}`
|
||||||
|
|
||||||
func TestUnmarshalMap(t *testing.T) {
|
func TestUnmarshalMap(t *testing.T) {
|
||||||
var m1 = Parse(exampleJSON).Value().(map[string]interface{})
|
m1 := Parse(exampleJSON).Value().(map[string]interface{})
|
||||||
var m2 map[string]interface{}
|
var m2 map[string]interface{}
|
||||||
if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
|
if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -795,9 +822,9 @@ func TestUnmarshalMap(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSingleArrayValue(t *testing.T) {
|
func TestSingleArrayValue(t *testing.T) {
|
||||||
var json = `{"key": "value","key2":[1,2,3,4,"A"]}`
|
json := `{"key": "value","key2":[1,2,3,4,"A"]}`
|
||||||
var result = Get(json, "key")
|
result := Get(json, "key")
|
||||||
var array = result.Array()
|
array := result.Array()
|
||||||
if len(array) != 1 {
|
if len(array) != 1 {
|
||||||
t.Fatal("array is empty")
|
t.Fatal("array is empty")
|
||||||
}
|
}
|
||||||
|
@ -814,7 +841,6 @@ func TestSingleArrayValue(t *testing.T) {
|
||||||
if len(array) != 0 {
|
if len(array) != 0 {
|
||||||
t.Fatalf("got '%v', expected '%v'", len(array), 0)
|
t.Fatalf("got '%v', expected '%v'", len(array), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var manyJSON = ` {
|
var manyJSON = ` {
|
||||||
|
@ -867,12 +893,15 @@ func TestManyBasic(t *testing.T) {
|
||||||
testMany(true, `[Cat Nancy]`, "name\\.first", "name.first")
|
testMany(true, `[Cat Nancy]`, "name\\.first", "name.first")
|
||||||
testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
|
testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMany(t *testing.T, json string, paths, expected []string) {
|
func testMany(t *testing.T, json string, paths, expected []string) {
|
||||||
testManyAny(t, json, paths, expected, true)
|
testManyAny(t, json, paths, expected, true)
|
||||||
testManyAny(t, json, paths, expected, false)
|
testManyAny(t, json, paths, expected, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testManyAny(t *testing.T, json string, paths, expected []string,
|
func testManyAny(t *testing.T, json string, paths, expected []string,
|
||||||
bytes bool) {
|
bytes bool,
|
||||||
|
) {
|
||||||
var result []Result
|
var result []Result
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
var which string
|
var which string
|
||||||
|
@ -902,6 +931,7 @@ func testManyAny(t *testing.T, json string, paths, expected []string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue20(t *testing.T) {
|
func TestIssue20(t *testing.T) {
|
||||||
json := `{ "name": "FirstName", "name1": "FirstName1", ` +
|
json := `{ "name": "FirstName", "name1": "FirstName1", ` +
|
||||||
`"address": "address1", "addressDetails": "address2", }`
|
`"address": "address1", "addressDetails": "address2", }`
|
||||||
|
@ -918,10 +948,14 @@ func TestIssue21(t *testing.T) {
|
||||||
"Level1Field4":4,
|
"Level1Field4":4,
|
||||||
"Level1Field2":{ "Level2Field1":[ "value1", "value2" ],
|
"Level1Field2":{ "Level2Field1":[ "value1", "value2" ],
|
||||||
"Level2Field2":{ "Level3Field1":[ { "key1":"value1" } ] } } }`
|
"Level2Field2":{ "Level3Field1":[ { "key1":"value1" } ] } } }`
|
||||||
paths := []string{"Level1Field1", "Level1Field2.Level2Field1",
|
paths := []string{
|
||||||
"Level1Field2.Level2Field2.Level3Field1", "Level1Field4"}
|
"Level1Field1", "Level1Field2.Level2Field1",
|
||||||
expected := []string{"3", `[ "value1", "value2" ]`,
|
"Level1Field2.Level2Field2.Level3Field1", "Level1Field4",
|
||||||
`[ { "key1":"value1" } ]`, "4"}
|
}
|
||||||
|
expected := []string{
|
||||||
|
"3", `[ "value1", "value2" ]`,
|
||||||
|
`[ { "key1":"value1" } ]`, "4",
|
||||||
|
}
|
||||||
t.Run("SingleMany", func(t *testing.T) {
|
t.Run("SingleMany", func(t *testing.T) {
|
||||||
testMany(t, json, paths,
|
testMany(t, json, paths,
|
||||||
expected)
|
expected)
|
||||||
|
@ -1097,8 +1131,10 @@ func TestValidBasic(t *testing.T) {
|
||||||
testvalid(t, "[-.123]", false)
|
testvalid(t, "[-.123]", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonchars = []string{"{", "[", ",", ":", "}", "]", "1", "0", "true",
|
var jsonchars = []string{
|
||||||
"false", "null", `""`, `"\""`, `"a"`}
|
"{", "[", ",", ":", "}", "]", "1", "0", "true",
|
||||||
|
"false", "null", `""`, `"\""`, `"a"`,
|
||||||
|
}
|
||||||
|
|
||||||
func makeRandomJSONChars(b []byte) {
|
func makeRandomJSONChars(b []byte) {
|
||||||
var bb []byte
|
var bb []byte
|
||||||
|
@ -1217,6 +1253,7 @@ func TestIssue55(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue58(t *testing.T) {
|
func TestIssue58(t *testing.T) {
|
||||||
json := `{"data":[{"uid": 1},{"uid": 2}]}`
|
json := `{"data":[{"uid": 1},{"uid": 2}]}`
|
||||||
res := Get(json, `data.#[uid!=1]`).Raw
|
res := Get(json, `data.#[uid!=1]`).Raw
|
||||||
|
@ -1279,11 +1316,10 @@ null
|
||||||
if i != 4 {
|
if i != 4 {
|
||||||
t.Fatalf("expected '%v', got '%v'", 4, i)
|
t.Fatalf("expected '%v', got '%v'", 4, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNumUint64String(t *testing.T) {
|
func TestNumUint64String(t *testing.T) {
|
||||||
var i int64 = 9007199254740993 //2^53 + 1
|
var i int64 = 9007199254740993 // 2^53 + 1
|
||||||
j := fmt.Sprintf(`{"data": [ %d, "hello" ] }`, i)
|
j := fmt.Sprintf(`{"data": [ %d, "hello" ] }`, i)
|
||||||
res := Get(j, "data.0")
|
res := Get(j, "data.0")
|
||||||
if res.String() != "9007199254740993" {
|
if res.String() != "9007199254740993" {
|
||||||
|
@ -1312,7 +1348,7 @@ func TestNumBigString(t *testing.T) {
|
||||||
|
|
||||||
func TestNumFloatString(t *testing.T) {
|
func TestNumFloatString(t *testing.T) {
|
||||||
var i int64 = -9007199254740993
|
var i int64 = -9007199254740993
|
||||||
j := fmt.Sprintf(`{"data":[ "hello", %d ]}`, i) //No quotes around value!!
|
j := fmt.Sprintf(`{"data":[ "hello", %d ]}`, i) // No quotes around value!!
|
||||||
res := Get(j, "data.1")
|
res := Get(j, "data.1")
|
||||||
if res.String() != "-9007199254740993" {
|
if res.String() != "-9007199254740993" {
|
||||||
t.Fatalf("expected '%v', got '%v'", "-9007199254740993", res.String())
|
t.Fatalf("expected '%v', got '%v'", "-9007199254740993", res.String())
|
||||||
|
@ -1321,7 +1357,7 @@ func TestNumFloatString(t *testing.T) {
|
||||||
|
|
||||||
func TestDuplicateKeys(t *testing.T) {
|
func TestDuplicateKeys(t *testing.T) {
|
||||||
// this is valid json according to the JSON spec
|
// this is valid json according to the JSON spec
|
||||||
var json = `{"name": "Alex","name": "Peter"}`
|
json := `{"name": "Alex","name": "Peter"}`
|
||||||
if Parse(json).Get("name").String() !=
|
if Parse(json).Get("name").String() !=
|
||||||
Parse(json).Map()["name"].String() {
|
Parse(json).Map()["name"].String() {
|
||||||
t.Fatalf("expected '%v', got '%v'",
|
t.Fatalf("expected '%v', got '%v'",
|
||||||
|
@ -1335,7 +1371,7 @@ func TestDuplicateKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayValues(t *testing.T) {
|
func TestArrayValues(t *testing.T) {
|
||||||
var json = `{"array": ["PERSON1","PERSON2",0],}`
|
json := `{"array": ["PERSON1","PERSON2",0],}`
|
||||||
values := Get(json, "array").Array()
|
values := Get(json, "array").Array()
|
||||||
var output string
|
var output string
|
||||||
for i, val := range values {
|
for i, val := range values {
|
||||||
|
@ -1354,7 +1390,6 @@ func TestArrayValues(t *testing.T) {
|
||||||
if output != expect {
|
if output != expect {
|
||||||
t.Fatalf("expected '%v', got '%v'", expect, output)
|
t.Fatalf("expected '%v', got '%v'", expect, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkValid(b *testing.B) {
|
func BenchmarkValid(b *testing.B) {
|
||||||
|
@ -1459,7 +1494,6 @@ func TestSplitPipe(t *testing.T) {
|
||||||
split(t, `hello.#[a|1="asdf\"|1324"]#|that.more|yikes`,
|
split(t, `hello.#[a|1="asdf\"|1324"]#|that.more|yikes`,
|
||||||
`hello.#[a|1="asdf\"|1324"]#`, "that.more|yikes", true)
|
`hello.#[a|1="asdf\"|1324"]#`, "that.more|yikes", true)
|
||||||
split(t, `a.#[]#\|b`, "", "", false)
|
split(t, `a.#[]#\|b`, "", "", false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayEx(t *testing.T) {
|
func TestArrayEx(t *testing.T) {
|
||||||
|
@ -1705,7 +1739,6 @@ func TestQueries(t *testing.T) {
|
||||||
assert(t, Get(json, `i*.f*.#[cust1>=true].first`).Exists())
|
assert(t, Get(json, `i*.f*.#[cust1>=true].first`).Exists())
|
||||||
assert(t, !Get(json, `i*.f*.#[cust2<false].first`).Exists())
|
assert(t, !Get(json, `i*.f*.#[cust2<false].first`).Exists())
|
||||||
assert(t, Get(json, `i*.f*.#[cust2<=false].first`).Exists())
|
assert(t, Get(json, `i*.f*.#[cust2<=false].first`).Exists())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryArrayValues(t *testing.T) {
|
func TestQueryArrayValues(t *testing.T) {
|
||||||
|
@ -1797,8 +1830,7 @@ func TestParseQuery(t *testing.T) {
|
||||||
var path, op, value, remain string
|
var path, op, value, remain string
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
path, op, value, remain, _, _, ok =
|
path, op, value, remain, _, _, ok = parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
|
||||||
parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
|
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `service_roles.#(=="one").()` &&
|
path == `service_roles.#(=="one").()` &&
|
||||||
op == "=" &&
|
op == "=" &&
|
||||||
|
@ -1826,8 +1858,7 @@ func TestParseQuery(t *testing.T) {
|
||||||
value == `` &&
|
value == `` &&
|
||||||
remain == ``)
|
remain == ``)
|
||||||
|
|
||||||
path, op, value, remain, _, _, ok =
|
path, op, value, remain, _, _, ok = parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
|
||||||
parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
|
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `a\("\"(".#(=="o\"(ne")` &&
|
path == `a\("\"(".#(=="o\"(ne")` &&
|
||||||
op == "%" &&
|
op == "%" &&
|
||||||
|
@ -1836,7 +1867,7 @@ func TestParseQuery(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentSubQuery(t *testing.T) {
|
func TestParentSubQuery(t *testing.T) {
|
||||||
var json = `{
|
json := `{
|
||||||
"topology": {
|
"topology": {
|
||||||
"instances": [
|
"instances": [
|
||||||
{
|
{
|
||||||
|
@ -1863,7 +1894,7 @@ func TestParentSubQuery(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSingleModifier(t *testing.T) {
|
func TestSingleModifier(t *testing.T) {
|
||||||
var data = `{"@key": "value"}`
|
data := `{"@key": "value"}`
|
||||||
assert(t, Get(data, "@key").String() == "value")
|
assert(t, Get(data, "@key").String() == "value")
|
||||||
assert(t, Get(data, "\\@key").String() == "value")
|
assert(t, Get(data, "\\@key").String() == "value")
|
||||||
}
|
}
|
||||||
|
@ -1943,9 +1974,9 @@ func TestValid(t *testing.T) {
|
||||||
assert(t, Get("[{}]", "@valid").Exists() == true)
|
assert(t, Get("[{}]", "@valid").Exists() == true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/tidwall/gjson/issues/152
|
// https://git.internal/re/gjson/issues/152
|
||||||
func TestJoin152(t *testing.T) {
|
func TestJoin152(t *testing.T) {
|
||||||
var json = `{
|
json := `{
|
||||||
"distance": 1374.0,
|
"distance": 1374.0,
|
||||||
"validFrom": "2005-11-14",
|
"validFrom": "2005-11-14",
|
||||||
"historical": {
|
"historical": {
|
||||||
|
@ -2086,7 +2117,6 @@ func TestVariousFuzz(t *testing.T) {
|
||||||
testJSON1 := `["*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,"]`
|
testJSON1 := `["*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,"]`
|
||||||
testJSON2 := `#[%"*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,""*,*"]`
|
testJSON2 := `#[%"*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,""*,*"]`
|
||||||
Get(testJSON1, testJSON2)
|
Get(testJSON1, testJSON2)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubpathsWithMultipaths(t *testing.T) {
|
func TestSubpathsWithMultipaths(t *testing.T) {
|
||||||
|
@ -2182,11 +2212,10 @@ func TestModifierDoubleQuotes(t *testing.T) {
|
||||||
`{"name":"Product P4","value":"{\"productId\":\"1cc3\",\"vendorId\":\"20de\"}"},`+
|
`{"name":"Product P4","value":"{\"productId\":\"1cc3\",\"vendorId\":\"20de\"}"},`+
|
||||||
`{"name":"Product P4","value":"{\"productId\":\"1dd3\",\"vendorId\":\"30de\"}"}`+
|
`{"name":"Product P4","value":"{\"productId\":\"1dd3\",\"vendorId\":\"30de\"}"}`+
|
||||||
`]`)
|
`]`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexes(t *testing.T) {
|
func TestIndexes(t *testing.T) {
|
||||||
var exampleJSON = `{
|
exampleJSON := `{
|
||||||
"vals": [
|
"vals": [
|
||||||
[1,66,{test: 3}],
|
[1,66,{test: 3}],
|
||||||
[4,5,[6]]
|
[4,5,[6]]
|
||||||
|
@ -2231,7 +2260,7 @@ func TestIndexes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexesMatchesRaw(t *testing.T) {
|
func TestIndexesMatchesRaw(t *testing.T) {
|
||||||
var exampleJSON = `{
|
exampleJSON := `{
|
||||||
"objectArray":[
|
"objectArray":[
|
||||||
{"first": "Jason", "age": 41},
|
{"first": "Jason", "age": 41},
|
||||||
{"first": "Dale", "age": 44},
|
{"first": "Dale", "age": 44},
|
||||||
|
@ -2267,7 +2296,7 @@ func TestIssue240(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeysValuesModifier(t *testing.T) {
|
func TestKeysValuesModifier(t *testing.T) {
|
||||||
var json = `{
|
json := `{
|
||||||
"1300014": {
|
"1300014": {
|
||||||
"code": "1300014",
|
"code": "1300014",
|
||||||
"price": 59.18,
|
"price": 59.18,
|
||||||
|
@ -2296,11 +2325,15 @@ func TestKeysValuesModifier(t *testing.T) {
|
||||||
|
|
||||||
func TestNaNInf(t *testing.T) {
|
func TestNaNInf(t *testing.T) {
|
||||||
json := `[+Inf,-Inf,Inf,iNF,-iNF,+iNF,NaN,nan,nAn,-0,+0]`
|
json := `[+Inf,-Inf,Inf,iNF,-iNF,+iNF,NaN,nan,nAn,-0,+0]`
|
||||||
raws := []string{"+Inf", "-Inf", "Inf", "iNF", "-iNF", "+iNF", "NaN", "nan",
|
raws := []string{
|
||||||
"nAn", "-0", "+0"}
|
"+Inf", "-Inf", "Inf", "iNF", "-iNF", "+iNF", "NaN", "nan",
|
||||||
nums := []float64{math.Inf(+1), math.Inf(-1), math.Inf(0), math.Inf(0),
|
"nAn", "-0", "+0",
|
||||||
|
}
|
||||||
|
nums := []float64{
|
||||||
|
math.Inf(+1), math.Inf(-1), math.Inf(0), math.Inf(0),
|
||||||
math.Inf(-1), math.Inf(+1), math.NaN(), math.NaN(), math.NaN(),
|
math.Inf(-1), math.Inf(+1), math.NaN(), math.NaN(), math.NaN(),
|
||||||
math.Copysign(0, -1), 0}
|
math.Copysign(0, -1), 0,
|
||||||
|
}
|
||||||
|
|
||||||
assert(t, int(Get(json, `#`).Int()) == len(raws))
|
assert(t, int(Get(json, `#`).Int()) == len(raws))
|
||||||
for i := 0; i < len(raws); i++ {
|
for i := 0; i < len(raws); i++ {
|
||||||
|
@ -2332,7 +2365,7 @@ func TestNaNInf(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmptyValueQuery(t *testing.T) {
|
func TestEmptyValueQuery(t *testing.T) {
|
||||||
// issue: https://github.com/tidwall/gjson/issues/246
|
// issue: https://git.internal/re/gjson/issues/246
|
||||||
assert(t, Get(
|
assert(t, Get(
|
||||||
`["ig","","tw","fb","tw","ig","tw"]`,
|
`["ig","","tw","fb","tw","ig","tw"]`,
|
||||||
`#(!="")#`).Raw ==
|
`#(!="")#`).Raw ==
|
||||||
|
@ -2589,5 +2622,4 @@ func TestIssue301(t *testing.T) {
|
||||||
assert(t, Get(json, `fav\.movie.[0]`).String() == `["Deer Hunter"]`)
|
assert(t, Get(json, `fav\.movie.[0]`).String() == `["Deer Hunter"]`)
|
||||||
assert(t, Get(json, `fav\.movie.1`).String() == "")
|
assert(t, Get(json, `fav\.movie.1`).String() == "")
|
||||||
assert(t, Get(json, `fav\.movie.[1]`).String() == "[]")
|
assert(t, Get(json, `fav\.movie.[1]`).String() == "[]")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue