mirror of https://github.com/tidwall/gjson.git
parent
35fa0d71c8
commit
0cbc0f402f
104
gjson.go
104
gjson.go
|
@ -1103,6 +1103,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
hit = pmatch && !rp.more
|
hit = pmatch && !rp.more
|
||||||
for ; i < len(c.json); i++ {
|
for ; i < len(c.json); i++ {
|
||||||
|
var num bool
|
||||||
switch c.json[i] {
|
switch c.json[i] {
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
|
@ -1150,15 +1151,13 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case 'n':
|
||||||
i, val = parseNumber(c.json, i)
|
if i+1 < len(c.json) && c.json[i+1] != 'u' {
|
||||||
if hit {
|
num = true
|
||||||
c.value.Raw = val
|
break
|
||||||
c.value.Type = Number
|
|
||||||
c.value.Num, _ = strconv.ParseFloat(val, 64)
|
|
||||||
return i, true
|
|
||||||
}
|
}
|
||||||
case 't', 'f', 'n':
|
fallthrough
|
||||||
|
case 't', 'f':
|
||||||
vc := c.json[i]
|
vc := c.json[i]
|
||||||
i, val = parseLiteral(c.json, i)
|
i, val = parseLiteral(c.json, i)
|
||||||
if hit {
|
if hit {
|
||||||
|
@ -1171,6 +1170,18 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
|
case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'i', 'I', 'N':
|
||||||
|
num = true
|
||||||
|
}
|
||||||
|
if num {
|
||||||
|
i, val = parseNumber(c.json, i)
|
||||||
|
if hit {
|
||||||
|
c.value.Raw = val
|
||||||
|
c.value.Type = Number
|
||||||
|
c.value.Num, _ = strconv.ParseFloat(val, 64)
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1358,6 +1369,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
} else {
|
} else {
|
||||||
ch = c.json[i]
|
ch = c.json[i]
|
||||||
}
|
}
|
||||||
|
var num bool
|
||||||
switch ch {
|
switch ch {
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
|
@ -1440,26 +1452,13 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case 'n':
|
||||||
i, val = parseNumber(c.json, i)
|
if i+1 < len(c.json) && c.json[i+1] != 'u' {
|
||||||
if rp.query.on {
|
num = true
|
||||||
var qval Result
|
break
|
||||||
qval.Raw = val
|
|
||||||
qval.Type = Number
|
|
||||||
qval.Num, _ = strconv.ParseFloat(val, 64)
|
|
||||||
if procQuery(qval) {
|
|
||||||
return i, true
|
|
||||||
}
|
|
||||||
} else if hit {
|
|
||||||
if rp.alogok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
c.value.Raw = val
|
|
||||||
c.value.Type = Number
|
|
||||||
c.value.Num, _ = strconv.ParseFloat(val, 64)
|
|
||||||
return i, true
|
|
||||||
}
|
}
|
||||||
case 't', 'f', 'n':
|
fallthrough
|
||||||
|
case 't', 'f':
|
||||||
vc := c.json[i]
|
vc := c.json[i]
|
||||||
i, val = parseLiteral(c.json, i)
|
i, val = parseLiteral(c.json, i)
|
||||||
if rp.query.on {
|
if rp.query.on {
|
||||||
|
@ -1487,6 +1486,9 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
|
case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'i', 'I', 'N':
|
||||||
|
num = true
|
||||||
case ']':
|
case ']':
|
||||||
if rp.arrch && rp.part == "#" {
|
if rp.arrch && rp.part == "#" {
|
||||||
if rp.alogok {
|
if rp.alogok {
|
||||||
|
@ -1562,6 +1564,26 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
return i + 1, false
|
return i + 1, false
|
||||||
}
|
}
|
||||||
|
if num {
|
||||||
|
i, val = parseNumber(c.json, i)
|
||||||
|
if rp.query.on {
|
||||||
|
var qval Result
|
||||||
|
qval.Raw = val
|
||||||
|
qval.Type = Number
|
||||||
|
qval.Num, _ = strconv.ParseFloat(val, 64)
|
||||||
|
if procQuery(qval) {
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
} else if hit {
|
||||||
|
if rp.alogok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c.value.Raw = val
|
||||||
|
c.value.Type = Number
|
||||||
|
c.value.Num, _ = strconv.ParseFloat(val, 64)
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2081,6 +2103,7 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
|
||||||
if json[i] <= ' ' {
|
if json[i] <= ' ' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
var num bool
|
||||||
switch json[i] {
|
switch json[i] {
|
||||||
case '"':
|
case '"':
|
||||||
i++
|
i++
|
||||||
|
@ -2100,15 +2123,13 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i, res, true
|
return i, res, true
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case 'n':
|
||||||
i, val = parseNumber(json, i)
|
if i+1 < len(json) && json[i+1] != 'u' {
|
||||||
if hit {
|
num = true
|
||||||
res.Raw = val
|
break
|
||||||
res.Type = Number
|
|
||||||
res.Num, _ = strconv.ParseFloat(val, 64)
|
|
||||||
}
|
}
|
||||||
return i, res, true
|
fallthrough
|
||||||
case 't', 'f', 'n':
|
case 't', 'f':
|
||||||
vc := json[i]
|
vc := json[i]
|
||||||
i, val = parseLiteral(json, i)
|
i, val = parseLiteral(json, i)
|
||||||
if hit {
|
if hit {
|
||||||
|
@ -2121,7 +2142,20 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
|
||||||
}
|
}
|
||||||
return i, res, true
|
return i, res, true
|
||||||
}
|
}
|
||||||
|
case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
|
'i', 'I', 'N':
|
||||||
|
num = true
|
||||||
}
|
}
|
||||||
|
if num {
|
||||||
|
i, val = parseNumber(json, i)
|
||||||
|
if hit {
|
||||||
|
res.Raw = val
|
||||||
|
res.Type = Number
|
||||||
|
res.Num, _ = strconv.ParseFloat(val, 64)
|
||||||
|
}
|
||||||
|
return i, res, true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return i, res, false
|
return i, res, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -2235,3 +2236,32 @@ func TestKeysValuesModifier(t *testing.T) {
|
||||||
assert(t, Get(`[]`, `@values`).String() == `[]`)
|
assert(t, Get(`[]`, `@values`).String() == `[]`)
|
||||||
assert(t, Get(`[1,2,3]`, `@values`).String() == `[1,2,3]`)
|
assert(t, Get(`[1,2,3]`, `@values`).String() == `[1,2,3]`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
math.Inf(-1), math.Inf(+1), math.NaN(), math.NaN(), math.NaN(),
|
||||||
|
math.Copysign(0, -1), 0}
|
||||||
|
|
||||||
|
// assert(t, int(Get(json, `#`).Int()) == len(raws))
|
||||||
|
for i := 0; i < len(raws); i++ {
|
||||||
|
r := Get(json, fmt.Sprintf("%d", i))
|
||||||
|
// fmt.Printf("%s %s\n", r.Raw, raws[i])
|
||||||
|
assert(t, r.Raw == raws[i])
|
||||||
|
// fmt.Printf("%f %f\n", r.Num, nums[i])
|
||||||
|
assert(t, r.Num == nums[i] || (math.IsNaN(r.Num) && math.IsNaN(nums[i])))
|
||||||
|
}
|
||||||
|
// println("------------")
|
||||||
|
var i int
|
||||||
|
Parse(json).ForEach(func(_, r Result) bool {
|
||||||
|
// fmt.Printf("%s %s\n", r.Raw, raws[i])
|
||||||
|
assert(t, r.Raw == raws[i])
|
||||||
|
// fmt.Printf("%f %f\n", r.Num, nums[i])
|
||||||
|
assert(t, r.Num == nums[i] || (math.IsNaN(r.Num) && math.IsNaN(nums[i])))
|
||||||
|
i++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue