forked from mirror/gjson
Fix string output for large integers
This fix makes calling String() on a JSON Number return the original value as it was represented in the JSON document for signed and unsigned integers. This ensures that very big (plus-53bit) integers are correctly returned. Floating points maintain their previous behavior [-+]?[0-9]*\.?[0-9]*. closes #74
This commit is contained in:
parent
f123b34087
commit
ba784d767a
15
gjson.go
15
gjson.go
|
@ -77,7 +77,20 @@ func (t Result) String() string {
|
||||||
case False:
|
case False:
|
||||||
return "false"
|
return "false"
|
||||||
case Number:
|
case Number:
|
||||||
|
if len(t.Raw) == 0 {
|
||||||
|
// calculated result
|
||||||
return strconv.FormatFloat(t.Num, 'f', -1, 64)
|
return strconv.FormatFloat(t.Num, 'f', -1, 64)
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
if t.Raw[0] == '-' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
for ; i < len(t.Raw); i++ {
|
||||||
|
if t.Raw[i] < '0' || t.Raw[i] > '9' {
|
||||||
|
return strconv.FormatFloat(t.Num, 'f', -1, 64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t.Raw
|
||||||
case String:
|
case String:
|
||||||
return t.Str
|
return t.Str
|
||||||
case JSON:
|
case JSON:
|
||||||
|
@ -1288,7 +1301,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
if rp.alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = ""
|
||||||
c.value.Type = Number
|
c.value.Type = Number
|
||||||
c.value.Num = float64(h - 1)
|
c.value.Num = float64(h - 1)
|
||||||
c.calcd = true
|
c.calcd = true
|
||||||
|
|
|
@ -479,7 +479,8 @@ func TestBasic4(t *testing.T) {
|
||||||
}
|
}
|
||||||
token = get(basicJSON, "arr.#")
|
token = get(basicJSON, "arr.#")
|
||||||
if token.String() != "6" {
|
if token.String() != "6" {
|
||||||
t.Fatal("expecting '6'", "got", token.String())
|
fmt.Printf("%#v\n", token)
|
||||||
|
t.Fatal("expecting 6", "got", token.String())
|
||||||
}
|
}
|
||||||
token = get(basicJSON, "arr.3.hello")
|
token = get(basicJSON, "arr.3.hello")
|
||||||
if token.String() != "world" {
|
if token.String() != "world" {
|
||||||
|
@ -1354,3 +1355,39 @@ null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNumUint64String(t *testing.T) {
|
||||||
|
i := 9007199254740993 //2^53 + 1
|
||||||
|
j := fmt.Sprintf(`{"data": [ %d, "hello" ] }`, i)
|
||||||
|
res := Get(j, "data.0")
|
||||||
|
if res.String() != "9007199254740993" {
|
||||||
|
t.Fatalf("expected '%v', got '%v'", "9007199254740993", res.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNumInt64String(t *testing.T) {
|
||||||
|
i := -9007199254740993
|
||||||
|
j := fmt.Sprintf(`{"data":[ "hello", %d ]}`, i)
|
||||||
|
res := Get(j, "data.1")
|
||||||
|
if res.String() != "-9007199254740993" {
|
||||||
|
t.Fatalf("expected '%v', got '%v'", "-9007199254740993", res.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNumBigString(t *testing.T) {
|
||||||
|
i := "900719925474099301239109123101" // very big
|
||||||
|
j := fmt.Sprintf(`{"data":[ "hello", "%s" ]}`, i)
|
||||||
|
res := Get(j, "data.1")
|
||||||
|
if res.String() != "900719925474099301239109123101" {
|
||||||
|
t.Fatalf("expected '%v', got '%v'", "900719925474099301239109123101", res.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNumFloatString(t *testing.T) {
|
||||||
|
i := -9007199254740993
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue