Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #17383: json.%,to and jsonutils.formJson,toJson now works with uint|uint64 #17389

Merged
merged 3 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions lib/pure/json.nim
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,21 @@ 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`.
result = JsonNode(kind: JInt, num: n)

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`.
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion lib/std/jsonutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
21 changes: 20 additions & 1 deletion tests/stdlib/tjson.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
15 changes: 15 additions & 0 deletions tests/stdlib/tjsonutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down