summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/json.nim22
-rw-r--r--lib/std/jsonutils.nim4
-rw-r--r--tests/stdlib/tjson.nim21
-rw-r--r--tests/stdlib/tjsonutils.nim15
4 files changed, 56 insertions, 6 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 51d4bb815..5feb81457 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -304,7 +304,10 @@ proc `%`*(s: string): JsonNode =
 
 proc `%`*(n: uint): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JInt JsonNode`.
-  result = JsonNode(kind: JInt, num: BiggestInt(n))
+  if n > cast[uint](int.high):
+    result = newJRawNumber($n)
+  else:
+    result = JsonNode(kind: JInt, num: BiggestInt(n))
 
 proc `%`*(n: int): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JInt JsonNode`.
@@ -312,7 +315,10 @@ proc `%`*(n: int): JsonNode =
 
 proc `%`*(n: BiggestUInt): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JInt JsonNode`.
-  result = JsonNode(kind: JInt, num: BiggestInt(n))
+  if n > cast[BiggestUInt](BiggestInt.high):
+    result = newJRawNumber($n)
+  else:
+    result = JsonNode(kind: JInt, num: BiggestInt(n))
 
 proc `%`*(n: BiggestInt): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JInt JsonNode`.
@@ -1055,8 +1061,16 @@ when defined(nimFixedForwardGeneric):
     dst = jsonNode.copy
 
   proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JInt}, jsonPath)
-    dst = T(jsonNode.num)
+    when T is uint|uint64:
+      case jsonNode.kind
+      of JString:
+        dst = T(parseBiggestUInt(jsonNode.str))
+      else:
+        verifyJsonKind(jsonNode, {JInt}, jsonPath)
+        dst = T(jsonNode.num)
+    else:
+      verifyJsonKind(jsonNode, {JInt}, jsonPath)
+      dst = cast[T](jsonNode.num)
 
   proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
     verifyJsonKind(jsonNode, {JInt, JFloat}, jsonPath)
diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim
index bbe6a7cd4..fa61d79db 100644
--- a/lib/std/jsonutils.nim
+++ b/lib/std/jsonutils.nim
@@ -187,7 +187,8 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
     of JInt: a = T(b.getBiggestInt())
     of JString: a = parseEnum[T](b.getStr())
     else: checkJson false, $($T, " ", b)
-  elif T is Ordinal: a = T(to(b, int))
+  elif T is uint|uint64: a = T(to(b, uint64))
+  elif T is Ordinal: a = cast[T](to(b, int))
   elif T is pointer: a = cast[pointer](to(b, int))
   elif T is distinct:
     when nimvm:
@@ -270,6 +271,7 @@ proc toJson*[T](a: T): JsonNode =
     # in simpler code for `toJson` and `fromJson`.
   elif T is distinct: result = toJson(a.distinctBase)
   elif T is bool: result = %(a)
+  elif T is SomeInteger: result = %a
   elif T is Ordinal: result = %(a.ord)
   else: result = %a
 
diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim
index 5508509ba..ceb9efb0e 100644
--- a/tests/stdlib/tjson.nim
+++ b/tests/stdlib/tjson.nim
@@ -7,7 +7,14 @@ discard """
 Note: Macro tests are in tests/stdlib/tjsonmacro.nim
 ]#
 
-import std/[json,parsejson,strutils,streams]
+import std/[json,parsejson,strutils]
+when not defined(js):
+  import std/streams
+
+proc testRoundtrip[T](t: T, expected: string) =
+  let j = %t
+  doAssert $j == expected, $j
+  doAssert %(j.to(T)) == j
 
 let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
 # nil passthrough
@@ -281,3 +288,15 @@ let jsonNode = %*mynode
 doAssert $jsonNode == """{"kind":"P","pChildren":[{"kind":"Text","textStr":"mychild"},{"kind":"Br"}]}"""
 doAssert $jsonNode.to(ContentNode) == """(kind: P, pChildren: @[(kind: Text, textStr: "mychild"), (kind: Br)])"""
 
+block: # bug #17383
+  testRoundtrip(int32.high): "2147483647"
+  testRoundtrip(uint32.high): "4294967295"
+  when int.sizeof == 4:
+    testRoundtrip(int.high): "2147483647"
+    testRoundtrip(uint.high): "4294967295"
+  else:
+    testRoundtrip(int.high): "9223372036854775807"
+    testRoundtrip(uint.high): "18446744073709551615"
+  when not defined(js):
+    testRoundtrip(int64.high): "9223372036854775807"
+    testRoundtrip(uint64.high): "18446744073709551615"
diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim
index beb12d5ae..5cd975cab 100644
--- a/tests/stdlib/tjsonutils.nim
+++ b/tests/stdlib/tjsonutils.nim
@@ -67,6 +67,21 @@ template fn() =
     doAssert b2.ord == 1 # explains the `1`
     testRoundtrip(a): """[1,2,3]"""
 
+  block: # bug #17383
+    block:
+      let a = (int32.high, uint32.high)
+      testRoundtrip(a): "[2147483647,4294967295]"
+    when not defined(js):
+      block:
+        let a = (int64.high, uint64.high)
+        testRoundtrip(a): "[9223372036854775807,18446744073709551615]"
+    block:
+      let a = (int.high, uint.high)
+      when int.sizeof == 4:
+        testRoundtrip(a): "[2147483647,4294967295]"
+      else:
+        testRoundtrip(a): "[9223372036854775807,18446744073709551615]"
+
   block: # case object
     type Foo = object
       x0: float