diff --git a/json_serialization/parser.nim b/json_serialization/parser.nim index 66e9b67..b84541b 100644 --- a/json_serialization/parser.nim +++ b/json_serialization/parser.nim @@ -13,7 +13,7 @@ import ./reader_desc, ./lexer -from json import JsonNode, JsonNodeKind, escapeJson +from json import JsonNode, JsonNodeKind, escapeJson, parseJson export reader_desc @@ -418,7 +418,7 @@ template parseObjectSkipNullFields*(r: var JsonReader, key: untyped, body: untyp body do: # error action r.raiseParserError() - + template parseObjectCustomKey*(r: var JsonReader, keyAction: untyped, body: untyped) = mixin flavorSkipNullFields type @@ -456,14 +456,23 @@ proc parseJsonNode(r: var JsonReader): JsonNode = of JsonValueKind.String: result = JsonNode(kind: JString, str: r.parseString()) of JsonValueKind.Number: - var val: JsonNumber[uint64] + var val: string r.lex.scanNumber(val) r.checkError - if val.isFloat: - result = JsonNode(kind: JFloat, fnum: r.toFloat(val, typeof(result.fnum))) + when (NimMajor, NimMinor) > (1,6): + try: + # Cannot access `newJRawNumber` directly, because it's not exported. + # But this should produce either JInt, JFloat, or JString/Raw + result = parseJson(val) + except ValueError as exc: + r.raiseUnexpectedValue(exc.msg) + except OSError as exc: + raiseAssert "parseJson here should not raise OSError exception: " & exc.msg else: - result = JsonNode(kind: JInt, num: - r.toInt(val, typeof(result.num), JsonReaderFlag.portableInt in r.lex.flags)) + try: + result = parseJson(val) + except Exception as exc: + r.raiseUnexpectedValue(exc.msg) of JsonValueKind.Object: result = JsonNode(kind: JObject) parseObjectImpl(r.lex, false): discard # initial action diff --git a/tests/test_parser.nim b/tests/test_parser.nim index 144b2b2..2a02785 100644 --- a/tests/test_parser.nim +++ b/tests/test_parser.nim @@ -330,6 +330,14 @@ const } } +""" + + jsonBigNum = """ +{ + "bignum": 9999999999999999999999999999999999999999999, + "float": 124.123, + "int": -12345 +} """ suite "Parse to runtime dynamic structure": @@ -345,6 +353,7 @@ suite "Parse to runtime dynamic structure": n["array"][0].bval == true n["array"][1].fnum == 567.89 n["array"][2].str == "string in array" + $n["array"][2] == "\"string in array\"" # quoted string n["array"][3].kind == JNull n["array"][4].kind == JArray n["array"][4].len == 1 @@ -358,6 +367,7 @@ suite "Parse to runtime dynamic structure": check: n["string"].strVal == "hello world" n["bool"].boolVal == true + n["int"].numVal.integer == 789 n["array"].len == 5 n["array"][0].boolVal == true n["array"][2].strVal == "string in array" @@ -366,14 +376,38 @@ suite "Parse to runtime dynamic structure": n["array"][4].len == 1 n["object"]["def"].boolVal == false + test "parse to json node bignum": + var r = toReader(jsonBigNum) + let n = r.parseJsonNode() + check: + n["bignum"].kind == JString + n["bignum"].str == "9999999999999999999999999999999999999999999" + $n["bignum"] == "9999999999999999999999999999999999999999999" # unquoted raw string + n["float"].kind == JFloat + n["float"].fnum == 124.123 + n["int"].kind == JInt + n["int"].num == -12345 + + test "parseValue bignum": + var r = toReader(jsonBigNum) + let n = r.parseValue(string) + check: + n["bignum"].kind == JsonValueKind.Number + n["bignum"].numVal.integer == "9999999999999999999999999999999999999999999" + + test "parseValue bignum overflow": + var r = toReader(jsonBigNum) + expect JsonReaderError: + let n = r.parseValue(uint64) + test "nim v2 regression #23233": # Nim compiler bug #23233 will prevent # compilation if both JsonValueRef[uint64] and JsonValueRef[string] # are instantiated at together. var r1 = toReader(jsonText) let n1 = r1.parseValue(uint64) - discard n1 + check n1["int"].numVal.integer == 789 var r2 = toReader(jsonText) let n2 = r2.parseValue(string) - discard n2 + check n2["int"].numVal.integer == "789"