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:
Josh Baker 2018-07-10 18:10:33 -07:00
parent f123b34087
commit ba784d767a
2 changed files with 53 additions and 3 deletions

View File

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

View File

@ -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())
}
}