summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/json.nim2
-rw-r--r--tests/stdlib/tjsonutils.nim17
2 files changed, 17 insertions, 2 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 3a9fa5898..d5bbb86b8 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -938,7 +938,7 @@ when defined(js):
     of "[object Array]": return JArray
     of "[object Object]": return JObject
     of "[object Number]":
-      if isInteger(x):
+      if isInteger(x) and 1.0 / cast[float](x) != -Inf: # preserve -0.0 as float
         if isSafeInteger(x):
           return JInt
         else:
diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim
index a55b0ca1d..62486b896 100644
--- a/tests/stdlib/tjsonutils.nim
+++ b/tests/stdlib/tjsonutils.nim
@@ -4,7 +4,8 @@ discard """
 
 import std/jsonutils
 import std/json
-from std/math import isNaN
+from std/math import isNaN, signbit
+from stdtest/testutils import whenRuntimeJs
 
 proc testRoundtrip[T](t: T, expected: string) =
   # checks that `T => json => T2 => json2` is such that json2 = json
@@ -123,6 +124,20 @@ template fn() =
     testRoundtripVal((Inf, -Inf, 0.0, -0.0, 1.0)): """["inf","-inf",0.0,-0.0,1.0]"""
     doAssert ($NaN.toJson).parseJson.jsonTo(float).isNaN
 
+  block: # bug #18009; unfixable unless we change parseJson (which would have overhead),
+         # but at least we can guarantee that the distinction between 0.0 and -0.0 is preserved.
+    let a = (0, 0.0, -0.0, 0.5, 1, 1.0)
+    testRoundtripVal(a): "[0,0.0,-0.0,0.5,1,1.0]"
+    let a2 = $($a.toJson).parseJson
+    whenRuntimeJs:
+      doAssert a2 == "[0,0,-0.0,0.5,1,1]"
+    do:
+      doAssert a2 == "[0,0.0,-0.0,0.5,1,1.0]"
+    let b = a2.parseJson.jsonTo(type(a))
+    doAssert not b[1].signbit
+    doAssert b[2].signbit
+    doAssert not b[3].signbit
+
   block: # case object
     type Foo = object
       x0: float