Format files before working on them

gjson_test.go was formatted with gofumpt
This commit is contained in:
ccoVeille 2024-04-23 13:35:22 +02:00
parent 2ba56cc086
commit 0b9aa79774
No known key found for this signature in database
4 changed files with 159 additions and 118 deletions

View File

@ -1,12 +1,12 @@
<p align="center">
<img
src="logo.png"
<img
src="logo.png"
width="240" height="78" border="0" alt="GJSON">
<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://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>
</p>
<p align="center">get json values quickly</a></p>
@ -34,7 +34,7 @@ $ go get -u github.com/tidwall/gjson
This will retrieve the library.
## Get a value
Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". When the value is found it's returned immediately.
Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". When the value is found it's returned immediately.
```go
package main
@ -93,9 +93,9 @@ The dot and wildcard characters can be escaped with '\\'.
"friends.1.last" >> "Craig"
```
You can also query an array for the first match by using `#(...)`, or find all
matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=`
comparison operators and the simple pattern matching `%` (like) and `!%`
You can also query an array for the first match by using `#(...)`, or find all
matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=`
comparison operators and the simple pattern matching `%` (like) and `!%`
(not like) operators.
```
@ -109,13 +109,13 @@ friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
changed in v1.3.0 as to avoid confusion with the new
[multipath](SYNTAX.md#multipaths) syntax. For backwards compatibility,
[multipath](SYNTAX.md#multipaths) syntax. For backwards compatibility,
`#[...]` will continue to work until the next major release.*
## Result Type
GJSON supports the json types `string`, `number`, `bool`, and `null`.
Arrays and Objects are returned as their raw json types.
GJSON supports the json types `string`, `number`, `bool`, and `null`.
Arrays and Objects are returned as their raw json types.
The `Result` type holds one of these:
@ -179,14 +179,14 @@ result.Int() int64 // -9223372036854775808 to 9223372036854775807
result.Uint() uint64 // 0 to 18446744073709551615
```
## Modifiers and path chaining
## Modifiers and path chaining
New in version 1.2 is support for modifier functions and path chaining.
A modifier is a path component that performs custom processing on the
A modifier is a path component that performs custom processing on the
json.
Multiple paths can be "chained" together using the pipe character.
Multiple paths can be "chained" together using the pipe character.
This is useful for getting results from a modified query.
For example, using the built-in `@reverse` modifier on the above json document,
@ -215,13 +215,13 @@ There are currently the following built-in modifiers:
### Modifier arguments
A modifier may accept an optional argument. The argument can be a valid JSON
A modifier may accept an optional argument. The argument can be a valid JSON
document or just characters.
For example, the `@pretty` modifier takes a json object as its argument.
For example, the `@pretty` modifier takes a json object as its argument.
```
@pretty:{"sortKeys":true}
@pretty:{"sortKeys":true}
```
Which makes the json pretty and orders all of its keys.
@ -240,7 +240,7 @@ Which makes the json pretty and orders all of its keys.
}
```
*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.*
### Custom modifiers
@ -269,7 +269,7 @@ gjson.AddModifier("case", func(json, arg string) string {
## JSON Lines
There's support for [JSON Lines](http://jsonlines.org/) using the `..` prefix, which treats a multilined document as an array.
There's support for [JSON Lines](http://jsonlines.org/) using the `..` prefix, which treats a multilined document as an array.
For example:
@ -305,14 +305,14 @@ Suppose you want all the last names from the following json:
{
"programmers": [
{
"firstName": "Janet",
"lastName": "McLaughlin",
"firstName": "Janet",
"lastName": "McLaughlin",
}, {
"firstName": "Elliotte",
"lastName": "Hunter",
"firstName": "Elliotte",
"lastName": "Hunter",
}, {
"firstName": "Jason",
"lastName": "Harold",
"firstName": "Jason",
"lastName": "Harold",
}
]
}
@ -336,7 +336,7 @@ println(name.String()) // prints "Elliotte"
## Iterate through an object or array
The `ForEach` function allows for quickly iterating through an object or array.
The `ForEach` function allows for quickly iterating through an object or array.
The key and value are passed to the iterator function for objects.
Only the value is passed for arrays.
Returning `false` from an iterator will stop iteration.
@ -344,7 +344,7 @@ Returning `false` from an iterator will stop iteration.
```go
result := gjson.Get(json, "programmers")
result.ForEach(func(key, value gjson.Result) bool {
println(value.String())
println(value.String())
return true // keep iterating
})
```
@ -363,7 +363,7 @@ gjson.Get(json, "name.last")
## Check for the existence of a value
Sometimes you just want to know if a value exists.
Sometimes you just want to know if a value exists.
```go
value := gjson.Get(json, "name.last")
@ -429,8 +429,8 @@ This is a best-effort no allocation sub slice of the original json. This method
## Performance
Benchmarks of GJSON alongside [encoding/json](https://golang.org/pkg/encoding/json/),
[ffjson](https://github.com/pquerna/ffjson),
Benchmarks of GJSON alongside [encoding/json](https://golang.org/pkg/encoding/json/),
[ffjson](https://github.com/pquerna/ffjson),
[EasyJSON](https://github.com/mailru/easyjson),
[jsonparser](https://github.com/buger/jsonparser),
and [json-iterator](https://github.com/json-iterator/go)
@ -459,7 +459,7 @@ JSON document used:
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"hOffset": 250,
"vOffset": 250,
@ -474,7 +474,7 @@ JSON document used:
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}
}
```
Each operation was rotated through one of the following search paths:

View File

@ -15,12 +15,12 @@ This document is designed to explain the structure of a GJSON Path through examp
- [Multipaths](#multipaths)
- [Literals](#literals)
The definitive implementation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
The definitive implementation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online.
## Path structure
A GJSON Path is intended to be easily expressed as a series of components separated by a `.` character.
A GJSON Path is intended to be easily expressed as a series of components separated by a `.` character.
Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, `!`, and `?`.
@ -44,7 +44,7 @@ Given this JSON
The following GJSON Paths evaluate to the accompanying values.
### Basic
### Basic
In many cases you'll just want to retrieve values by object name or array index.
@ -61,7 +61,7 @@ friends.1.first "Roger"
### Wildcards
A key may contain the special wildcard characters `*` and `?`.
A key may contain the special wildcard characters `*` and `?`.
The `*` will match on any zero+ characters, and `?` matches on any one character.
```go
@ -71,7 +71,7 @@ c?ildren.0 "Sara"
### Escape character
Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`.
Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`.
```go
fav\.movie "Deer Hunter"
@ -82,13 +82,13 @@ You'll also need to make sure that the `\` character is correctly escaped when h
```go
// Go
val := gjson.Get(json, "fav\\.movie") // must escape the slash
val := gjson.Get(json, `fav\.movie`) // no need to escape the slash
val := gjson.Get(json, `fav\.movie`) // no need to escape the slash
```
```rust
// Rust
let val = gjson::get(json, "fav\\.movie") // must escape the slash
let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash
let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash
```
@ -105,8 +105,8 @@ friends.#.age [44,68,47]
### Queries
You can also query an array for the first match by using `#(...)`, or find all matches with `#(...)#`.
Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators,
You can also query an array for the first match by using `#(...)`, or find all matches with `#(...)#`.
Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators,
and the simple pattern matching `%` (like) and `!%` (not like) operators.
```go
@ -131,7 +131,7 @@ friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
```
*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
changed in v1.3.0 as to avoid confusion with the new [multipath](#multipaths)
changed in v1.3.0 as to avoid confusion with the new [multipath](#multipaths)
syntax. For backwards compatibility, `#[...]` will continue to work until the
next major release.*
@ -185,9 +185,9 @@ vals.#(b!=~*)#.a >> [11]
### Dot vs Pipe
The `.` is standard separator, but it's also possible to use a `|`.
The `.` is standard separator, but it's also possible to use a `|`.
In most cases they both end up returning the same results.
The cases where`|` differs from `.` is when it's used after the `#` for [Arrays](#arrays) and [Queries](#queries).
The cases where`|` differs from `.` is when it's used after the `#` for [Arrays](#arrays) and [Queries](#queries).
Here are some examples
@ -221,8 +221,8 @@ The `.first` suffix will process the `first` path on each array element *before*
["Dale","Jane"]
```
But the `|first` suffix actually processes the `first` path *after* the previous result.
Since the previous result is an array, not an object, it's not possible to process
But the `|first` suffix actually processes the `first` path *after* the previous result.
Since the previous result is an array, not an object, it's not possible to process
because `first` does not exist.
Yet, `|0` suffix returns
@ -286,12 +286,12 @@ Which makes the json pretty and orders all of its keys.
}
```
*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.*
#### Custom modifiers
You can also add custom modifiers.
You can also add custom modifiers.
For example, here we create a modifier which makes the entire JSON payload upper or lower case.
@ -323,11 +323,11 @@ For example, using the given multipath:
{name.first,age,"the_murphys":friends.#(last="Murphy")#.first}
```
Here we selected the first name, age, and the first name for friends with the
Here we selected the first name, age, and the first name for friends with the
last name "Murphy".
You'll notice that an optional key can be provided, in this case
"the_murphys", to force assign a key to a value. Otherwise, the name of the
You'll notice that an optional key can be provided, in this case
"the_murphys", to force assign a key to a value. Otherwise, the name of the
actual field will be used, in this case "first". If a name cannot be
determined, then "_" is used.
@ -339,9 +339,9 @@ This results in
### Literals
Starting with v1.12.0, GJSON added support of json literals, which provides a way for constructing static blocks of json. This is can be particularly useful when constructing a new json document using [multipaths](#multipaths).
Starting with v1.12.0, GJSON added support of json literals, which provides a way for constructing static blocks of json. This is can be particularly useful when constructing a new json document using [multipaths](#multipaths).
A json literal begins with the '!' declaration character.
A json literal begins with the '!' declaration character.
For example, using the given multipath:
@ -351,7 +351,7 @@ For example, using the given multipath:
Here we selected the first name and age. Then add two new fields, "company" and "employed".
This results in
This results in
```json
{"first":"Tom","age":37,"company":"Happysoft","employed":true}

View File

@ -334,7 +334,7 @@ type arrayOrMapResult struct {
}
func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
var json = t.Raw
json := t.Raw
var i int
var value Result
var count int
@ -686,7 +686,7 @@ func (t Result) Value() interface{} {
}
func parseString(json string, i int) (int, string, bool, bool) {
var s = i
s := i
for ; i < len(json); i++ {
if json[i] > '\\' {
continue
@ -724,7 +724,7 @@ func parseString(json string, i int) (int, string, bool, bool) {
}
func parseNumber(json string, i int) (int, string) {
var s = i
s := i
i++
for ; i < len(json); i++ {
if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||
@ -736,7 +736,7 @@ func parseNumber(json string, i int) (int, string) {
}
func parseLiteral(json string, i int) (int, string) {
var s = i
s := i
i++
for ; i < len(json); i++ {
if json[i] < 'a' || json[i] > 'z' {
@ -793,8 +793,7 @@ func parseArrayPath(path string) (r arrayPathResult) {
} else if path[1] == '[' || path[1] == '(' {
// query
r.query.on = true
qpath, op, value, _, fi, vesc, ok :=
parseQuery(path[i:])
qpath, op, value, _, fi, vesc, ok := parseQuery(path[i:])
if !ok {
// bad query, end now
break
@ -1103,7 +1102,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
// this is slightly different from getting s string value
// because we don't need the outer quotes.
i++
var s = i
s := i
for ; i < len(c.json); i++ {
if c.json[i] > '\\' {
continue
@ -1400,6 +1399,7 @@ func queryMatches(rp *arrayPathResult, value Result) bool {
}
return false
}
func parseArray(c *parseContext, i int, path string) (int, bool) {
var pmatch, vesc, ok, hit bool
var val string
@ -1619,8 +1619,8 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
c.pipe = right
c.piped = true
}
var indexes = make([]int, 0, 64)
var jsons = make([]byte, 0, 64)
indexes := make([]int, 0, 64)
jsons := make([]byte, 0, 64)
jsons = append(jsons, '[')
for j, k := 0, 0; j < len(alog); j++ {
idx := alog[j]
@ -2095,7 +2095,7 @@ func Get(json, path string) Result {
}
}
var i int
var c = &parseContext{json: json}
c := &parseContext{json: json}
if len(path) >= 2 && path[0] == '.' && path[1] == '.' {
c.lines = true
parseArray(c, 0, path[2:])
@ -2136,7 +2136,7 @@ func runeit(json string) rune {
// unescape unescapes a string
func unescape(json string) string {
var str = make([]byte, 0, len(json))
str := make([]byte, 0, len(json))
for i := 0; i < len(json); i++ {
switch {
default:
@ -2377,6 +2377,7 @@ func validpayload(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validany(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ {
switch data[i] {
@ -2402,6 +2403,7 @@ func validany(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validobject(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ {
switch data[i] {
@ -2444,6 +2446,7 @@ func validobject(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validcolon(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ {
switch data[i] {
@ -2457,6 +2460,7 @@ func validcolon(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
for ; i < len(data); i++ {
switch data[i] {
@ -2472,6 +2476,7 @@ func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
}
return i, false
}
func validarray(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ {
switch data[i] {
@ -2495,6 +2500,7 @@ func validarray(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validstring(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ {
if data[i] < ' ' {
@ -2527,6 +2533,7 @@ func validstring(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validnumber(data []byte, i int) (outi int, ok bool) {
i--
// sign
@ -2609,6 +2616,7 @@ func validtrue(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validfalse(data []byte, i int) (outi int, ok bool) {
if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&
data[i+2] == 's' && data[i+3] == 'e' {
@ -2616,6 +2624,7 @@ func validfalse(data []byte, i int) (outi int, ok bool) {
}
return i, false
}
func validnull(data []byte, i int) (outi int, ok bool) {
if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&
data[i+2] == 'l' {

View File

@ -199,7 +199,6 @@ func TestPath(t *testing.T) {
get("loggy.programmers.2.email")
get("lastly.end\\.\\.\\.ing")
get("lastly.yay")
}
func TestTimeResult(t *testing.T) {
@ -216,8 +215,10 @@ func TestParseAny(t *testing.T) {
func TestManyVariousPathCounts(t *testing.T) {
json := `{"a":"a","b":"b","c":"c"}`
counts := []int{3, 4, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127,
128, 129, 255, 256, 257, 511, 512, 513}
counts := []int{
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"}
expects := []string{"a", "b", "c"}
for _, count := range counts {
@ -238,6 +239,7 @@ func TestManyVariousPathCounts(t *testing.T) {
}
}
}
func TestManyRecursion(t *testing.T) {
var json string
var path string
@ -252,6 +254,7 @@ func TestManyRecursion(t *testing.T) {
path = path[1:]
assert(t, GetMany(json, path)[0].String() == "b")
}
func TestByteSafety(t *testing.T) {
jsonb := []byte(`{"name":"Janet","age":38}`)
mtok := GetBytes(jsonb, "name")
@ -348,6 +351,7 @@ func TestPlus53BitInts(t *testing.T) {
// flip the number to the negative sign.
assert(t, Get(json, "overflow_int64").Int() == -9223372036854775808)
}
func TestIssue38(t *testing.T) {
// These should not fail, even though the unicode is invalid.
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\u1345asd"]`, "0")
}
func TestTypes(t *testing.T) {
assert(t, (Result{Type: String}).Type.String() == "String")
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: Number, Num: 1}).Float() == 1)
}
func TestForEach(t *testing.T) {
Result{}.ForEach(nil)
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(`{"ok":"bad`)).ForEach(nil)
}
func TestMap(t *testing.T) {
assert(t, len(ParseBytes([]byte(`"asdf"`)).Map()) == 0)
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: "{"}.Map() != nil)
}
func TestBasic1(t *testing.T) {
mtok := get(basicJSON, `loggy.programmers`)
var count int
@ -474,6 +482,7 @@ func TestBasic1(t *testing.T) {
t.Fatalf("expected %v, got %v", 3, count)
}
}
func TestBasic2(t *testing.T) {
mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`)
if mtok.String() != "1002.3" {
@ -509,6 +518,7 @@ func TestBasic2(t *testing.T) {
mtok.Map()["programmers"].Array()[1].Map()["firstName"].Str)
}
}
func TestBasic3(t *testing.T) {
var mtok Result
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()))
}
}
func TestBasic4(t *testing.T) {
if get(basicJSON, "items.3.tags.#").Num != 3 {
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")
}
}
func TestBasic5(t *testing.T) {
token := get(basicJSON, "age")
if token.String() != "100" {
@ -630,8 +642,9 @@ func TestBasic5(t *testing.T) {
t.Fatalf("expecting %v, got %v", "Jason", fn)
}
}
func TestUnicode(t *testing.T) {
var json = `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
json := `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
if Get(json, "的情况下解.key").Num != 1 {
t.Fatal("fail")
}
@ -659,11 +672,13 @@ func TestUnescape(t *testing.T) {
unescape(string([]byte{'\\', '\\', 0}))
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
}
func assert(t testing.TB, cond bool) {
if !cond {
panic("assert failed")
}
}
func TestLess(t *testing.T) {
assert(t, !Result{Type: Null}.Less(Result{Type: Null}, 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: False}.Less(Result{Type: Null}, true))
assert(t, Result{Type: False}.Less(Result{Type: True}, true))
assert(t, Result{Type: String, Str: "abc"}.Less(Result{Type: String,
Str: "bcd"}, true))
assert(t, Result{Type: String, Str: "ABC"}.Less(Result{Type: String,
Str: "abc"}, true))
assert(t, !Result{Type: String, Str: "ABC"}.Less(Result{Type: String,
Str: "abc"}, 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, Result{Type: String, Str: "abc"}.Less(Result{
Type: String,
Str: "bcd",
}, true))
assert(t, Result{Type: String, Str: "ABC"}.Less(Result{
Type: String,
Str: "abc",
}, true))
assert(t, !Result{Type: String, Str: "ABC"}.Less(Result{
Type: String,
Str: "abc",
}, 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"))
@ -776,7 +803,7 @@ var exampleJSON = `{
}`
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{}
if err := json.Unmarshal([]byte(exampleJSON), &m2); err != nil {
t.Fatal(err)
@ -795,9 +822,9 @@ func TestUnmarshalMap(t *testing.T) {
}
func TestSingleArrayValue(t *testing.T) {
var json = `{"key": "value","key2":[1,2,3,4,"A"]}`
var result = Get(json, "key")
var array = result.Array()
json := `{"key": "value","key2":[1,2,3,4,"A"]}`
result := Get(json, "key")
array := result.Array()
if len(array) != 1 {
t.Fatal("array is empty")
}
@ -814,7 +841,6 @@ func TestSingleArrayValue(t *testing.T) {
if len(array) != 0 {
t.Fatalf("got '%v', expected '%v'", len(array), 0)
}
}
var manyJSON = ` {
@ -867,12 +893,15 @@ func TestManyBasic(t *testing.T) {
testMany(true, `[Cat Nancy]`, "name\\.first", "name.first")
testMany(true, `[world]`, strings.Repeat("a.", 70)+"hello")
}
func testMany(t *testing.T, json string, paths, expected []string) {
testManyAny(t, json, paths, expected, true)
testManyAny(t, json, paths, expected, false)
}
func testManyAny(t *testing.T, json string, paths, expected []string,
bytes bool) {
bytes bool,
) {
var result []Result
for i := 0; i < 2; i++ {
var which string
@ -902,6 +931,7 @@ func testManyAny(t *testing.T, json string, paths, expected []string,
}
}
}
func TestIssue20(t *testing.T) {
json := `{ "name": "FirstName", "name1": "FirstName1", ` +
`"address": "address1", "addressDetails": "address2", }`
@ -918,10 +948,14 @@ func TestIssue21(t *testing.T) {
"Level1Field4":4,
"Level1Field2":{ "Level2Field1":[ "value1", "value2" ],
"Level2Field2":{ "Level3Field1":[ { "key1":"value1" } ] } } }`
paths := []string{"Level1Field1", "Level1Field2.Level2Field1",
"Level1Field2.Level2Field2.Level3Field1", "Level1Field4"}
expected := []string{"3", `[ "value1", "value2" ]`,
`[ { "key1":"value1" } ]`, "4"}
paths := []string{
"Level1Field1", "Level1Field2.Level2Field1",
"Level1Field2.Level2Field2.Level3Field1", "Level1Field4",
}
expected := []string{
"3", `[ "value1", "value2" ]`,
`[ { "key1":"value1" } ]`, "4",
}
t.Run("SingleMany", func(t *testing.T) {
testMany(t, json, paths,
expected)
@ -1097,8 +1131,10 @@ func TestValidBasic(t *testing.T) {
testvalid(t, "[-.123]", false)
}
var jsonchars = []string{"{", "[", ",", ":", "}", "]", "1", "0", "true",
"false", "null", `""`, `"\""`, `"a"`}
var jsonchars = []string{
"{", "[", ",", ":", "}", "]", "1", "0", "true",
"false", "null", `""`, `"\""`, `"a"`,
}
func makeRandomJSONChars(b []byte) {
var bb []byte
@ -1217,6 +1253,7 @@ func TestIssue55(t *testing.T) {
}
}
}
func TestIssue58(t *testing.T) {
json := `{"data":[{"uid": 1},{"uid": 2}]}`
res := Get(json, `data.#[uid!=1]`).Raw
@ -1279,11 +1316,10 @@ null
if i != 4 {
t.Fatalf("expected '%v', got '%v'", 4, i)
}
}
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)
res := Get(j, "data.0")
if res.String() != "9007199254740993" {
@ -1312,7 +1348,7 @@ func TestNumBigString(t *testing.T) {
func TestNumFloatString(t *testing.T) {
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")
if res.String() != "-9007199254740993" {
t.Fatalf("expected '%v', got '%v'", "-9007199254740993", res.String())
@ -1321,7 +1357,7 @@ func TestNumFloatString(t *testing.T) {
func TestDuplicateKeys(t *testing.T) {
// 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() !=
Parse(json).Map()["name"].String() {
t.Fatalf("expected '%v', got '%v'",
@ -1335,7 +1371,7 @@ func TestDuplicateKeys(t *testing.T) {
}
func TestArrayValues(t *testing.T) {
var json = `{"array": ["PERSON1","PERSON2",0],}`
json := `{"array": ["PERSON1","PERSON2",0],}`
values := Get(json, "array").Array()
var output string
for i, val := range values {
@ -1354,7 +1390,6 @@ func TestArrayValues(t *testing.T) {
if output != expect {
t.Fatalf("expected '%v', got '%v'", expect, output)
}
}
func BenchmarkValid(b *testing.B) {
@ -1459,7 +1494,6 @@ func TestSplitPipe(t *testing.T) {
split(t, `hello.#[a|1="asdf\"|1324"]#|that.more|yikes`,
`hello.#[a|1="asdf\"|1324"]#`, "that.more|yikes", true)
split(t, `a.#[]#\|b`, "", "", false)
}
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*.#[cust2<false].first`).Exists())
assert(t, Get(json, `i*.f*.#[cust2<=false].first`).Exists())
}
func TestQueryArrayValues(t *testing.T) {
@ -1797,8 +1830,7 @@ func TestParseQuery(t *testing.T) {
var path, op, value, remain string
var ok bool
path, op, value, remain, _, _, ok =
parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
path, op, value, remain, _, _, ok = parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
assert(t, ok &&
path == `service_roles.#(=="one").()` &&
op == "=" &&
@ -1826,8 +1858,7 @@ func TestParseQuery(t *testing.T) {
value == `` &&
remain == ``)
path, op, value, remain, _, _, ok =
parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
path, op, value, remain, _, _, ok = parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
assert(t, ok &&
path == `a\("\"(".#(=="o\"(ne")` &&
op == "%" &&
@ -1836,7 +1867,7 @@ func TestParseQuery(t *testing.T) {
}
func TestParentSubQuery(t *testing.T) {
var json = `{
json := `{
"topology": {
"instances": [
{
@ -1863,7 +1894,7 @@ func TestParentSubQuery(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")
}
@ -1945,7 +1976,7 @@ func TestValid(t *testing.T) {
// https://github.com/tidwall/gjson/issues/152
func TestJoin152(t *testing.T) {
var json = `{
json := `{
"distance": 1374.0,
"validFrom": "2005-11-14",
"historical": {
@ -2086,7 +2117,6 @@ func TestVariousFuzz(t *testing.T) {
testJSON1 := `["*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,"]`
testJSON2 := `#[%"*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,""*,*"]`
Get(testJSON1, testJSON2)
}
func TestSubpathsWithMultipaths(t *testing.T) {
@ -2227,11 +2257,10 @@ func TestModifierDoubleQuotes(t *testing.T) {
`{"name":"Product P4","value":"{\"productId\":\"1cc3\",\"vendorId\":\"20de\"}"},`+
`{"name":"Product P4","value":"{\"productId\":\"1dd3\",\"vendorId\":\"30de\"}"}`+
`]`)
}
func TestIndexes(t *testing.T) {
var exampleJSON = `{
exampleJSON := `{
"vals": [
[1,66,{test: 3}],
[4,5,[6]]
@ -2276,7 +2305,7 @@ func TestIndexes(t *testing.T) {
}
func TestIndexesMatchesRaw(t *testing.T) {
var exampleJSON = `{
exampleJSON := `{
"objectArray":[
{"first": "Jason", "age": 41},
{"first": "Dale", "age": 44},
@ -2312,7 +2341,7 @@ func TestIssue240(t *testing.T) {
}
func TestKeysValuesModifier(t *testing.T) {
var json = `{
json := `{
"1300014": {
"code": "1300014",
"price": 59.18,
@ -2341,11 +2370,15 @@ func TestKeysValuesModifier(t *testing.T) {
func TestNaNInf(t *testing.T) {
json := `[+Inf,-Inf,Inf,iNF,-iNF,+iNF,NaN,nan,nAn,-0,+0]`
raws := []string{"+Inf", "-Inf", "Inf", "iNF", "-iNF", "+iNF", "NaN", "nan",
"nAn", "-0", "+0"}
nums := []float64{math.Inf(+1), math.Inf(-1), math.Inf(0), math.Inf(0),
raws := []string{
"+Inf", "-Inf", "Inf", "iNF", "-iNF", "+iNF", "NaN", "nan",
"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.Copysign(0, -1), 0}
math.Copysign(0, -1), 0,
}
assert(t, int(Get(json, `#`).Int()) == len(raws))
for i := 0; i < len(raws); i++ {
@ -2579,7 +2612,7 @@ func TestJSONString(t *testing.T) {
testJSONString(t, "R\xfd\xfc\a!\x82eO\x16?_\x0f\x9ab\x1dr")
testJSONString(t, "_\xb9\v\xad\xb3|X!\xb6\xd9U&\xa4\x1a\x95\x04")
data, _ := json.Marshal("\b\f")
if (string(data) == "\"\\b\\f\"") {
if string(data) == "\"\\b\\f\"" {
// Go version 1.22+ encodes "\b" and "\f" correctly.
testJSONString(t, "\b\f")
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
@ -2639,7 +2672,6 @@ func TestIssue301(t *testing.T) {
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() == "[]")
}
func TestModDig(t *testing.T) {