Skip to content

Commit d217888

Browse files
authored
close #18009 parseJson JInt vs JFloat; preserve -0.0 as JFloat to distinguish from 0.0 (#18067)
1 parent 1421a3b commit d217888

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

lib/pure/json.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ when defined(js):
938938
of "[object Array]": return JArray
939939
of "[object Object]": return JObject
940940
of "[object Number]":
941-
if isInteger(x):
941+
if isInteger(x) and 1.0 / cast[float](x) != -Inf: # preserve -0.0 as float
942942
if isSafeInteger(x):
943943
return JInt
944944
else:

tests/stdlib/tjsonutils.nim

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ discard """
44

55
import std/jsonutils
66
import std/json
7-
from std/math import isNaN
7+
from std/math import isNaN, signbit
8+
from stdtest/testutils import whenRuntimeJs
89

910
proc testRoundtrip[T](t: T, expected: string) =
1011
# checks that `T => json => T2 => json2` is such that json2 = json
@@ -123,6 +124,20 @@ template fn() =
123124
testRoundtripVal((Inf, -Inf, 0.0, -0.0, 1.0)): """["inf","-inf",0.0,-0.0,1.0]"""
124125
doAssert ($NaN.toJson).parseJson.jsonTo(float).isNaN
125126

127+
block: # bug #18009; unfixable unless we change parseJson (which would have overhead),
128+
# but at least we can guarantee that the distinction between 0.0 and -0.0 is preserved.
129+
let a = (0, 0.0, -0.0, 0.5, 1, 1.0)
130+
testRoundtripVal(a): "[0,0.0,-0.0,0.5,1,1.0]"
131+
let a2 = $($a.toJson).parseJson
132+
whenRuntimeJs:
133+
doAssert a2 == "[0,0,-0.0,0.5,1,1]"
134+
do:
135+
doAssert a2 == "[0,0.0,-0.0,0.5,1,1.0]"
136+
let b = a2.parseJson.jsonTo(type(a))
137+
doAssert not b[1].signbit
138+
doAssert b[2].signbit
139+
doAssert not b[3].signbit
140+
126141
block: # case object
127142
type Foo = object
128143
x0: float

0 commit comments

Comments
 (0)