Skip to content

Commit fd81708

Browse files
authored
Add support for newJRawNumber when parsing large numbers to JsonNode (#110)
* Add support for newJRawNumber when parsing large numbers to JsonNode * Fix exception handling * Remove lagacy JsonNode number parser
1 parent 5a9a8ba commit fd81708

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

json_serialization/parser.nim

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import
1313
./reader_desc,
1414
./lexer
1515

16-
from json import JsonNode, JsonNodeKind, escapeJson
16+
from json import JsonNode, JsonNodeKind, escapeJson, parseJson
1717

1818
export
1919
reader_desc
@@ -418,7 +418,7 @@ template parseObjectSkipNullFields*(r: var JsonReader, key: untyped, body: untyp
418418
body
419419
do: # error action
420420
r.raiseParserError()
421-
421+
422422
template parseObjectCustomKey*(r: var JsonReader, keyAction: untyped, body: untyped) =
423423
mixin flavorSkipNullFields
424424
type
@@ -456,14 +456,23 @@ proc parseJsonNode(r: var JsonReader): JsonNode =
456456
of JsonValueKind.String:
457457
result = JsonNode(kind: JString, str: r.parseString())
458458
of JsonValueKind.Number:
459-
var val: JsonNumber[uint64]
459+
var val: string
460460
r.lex.scanNumber(val)
461461
r.checkError
462-
if val.isFloat:
463-
result = JsonNode(kind: JFloat, fnum: r.toFloat(val, typeof(result.fnum)))
462+
when (NimMajor, NimMinor) > (1,6):
463+
try:
464+
# Cannot access `newJRawNumber` directly, because it's not exported.
465+
# But this should produce either JInt, JFloat, or JString/Raw
466+
result = parseJson(val)
467+
except ValueError as exc:
468+
r.raiseUnexpectedValue(exc.msg)
469+
except OSError as exc:
470+
raiseAssert "parseJson here should not raise OSError exception: " & exc.msg
464471
else:
465-
result = JsonNode(kind: JInt, num:
466-
r.toInt(val, typeof(result.num), JsonReaderFlag.portableInt in r.lex.flags))
472+
try:
473+
result = parseJson(val)
474+
except Exception as exc:
475+
r.raiseUnexpectedValue(exc.msg)
467476
of JsonValueKind.Object:
468477
result = JsonNode(kind: JObject)
469478
parseObjectImpl(r.lex, false): discard # initial action

tests/test_parser.nim

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,14 @@ const
330330
}
331331
}
332332
333+
"""
334+
335+
jsonBigNum = """
336+
{
337+
"bignum": 9999999999999999999999999999999999999999999,
338+
"float": 124.123,
339+
"int": -12345
340+
}
333341
"""
334342

335343
suite "Parse to runtime dynamic structure":
@@ -345,6 +353,7 @@ suite "Parse to runtime dynamic structure":
345353
n["array"][0].bval == true
346354
n["array"][1].fnum == 567.89
347355
n["array"][2].str == "string in array"
356+
$n["array"][2] == "\"string in array\"" # quoted string
348357
n["array"][3].kind == JNull
349358
n["array"][4].kind == JArray
350359
n["array"][4].len == 1
@@ -358,6 +367,7 @@ suite "Parse to runtime dynamic structure":
358367
check:
359368
n["string"].strVal == "hello world"
360369
n["bool"].boolVal == true
370+
n["int"].numVal.integer == 789
361371
n["array"].len == 5
362372
n["array"][0].boolVal == true
363373
n["array"][2].strVal == "string in array"
@@ -366,14 +376,38 @@ suite "Parse to runtime dynamic structure":
366376
n["array"][4].len == 1
367377
n["object"]["def"].boolVal == false
368378

379+
test "parse to json node bignum":
380+
var r = toReader(jsonBigNum)
381+
let n = r.parseJsonNode()
382+
check:
383+
n["bignum"].kind == JString
384+
n["bignum"].str == "9999999999999999999999999999999999999999999"
385+
$n["bignum"] == "9999999999999999999999999999999999999999999" # unquoted raw string
386+
n["float"].kind == JFloat
387+
n["float"].fnum == 124.123
388+
n["int"].kind == JInt
389+
n["int"].num == -12345
390+
391+
test "parseValue bignum":
392+
var r = toReader(jsonBigNum)
393+
let n = r.parseValue(string)
394+
check:
395+
n["bignum"].kind == JsonValueKind.Number
396+
n["bignum"].numVal.integer == "9999999999999999999999999999999999999999999"
397+
398+
test "parseValue bignum overflow":
399+
var r = toReader(jsonBigNum)
400+
expect JsonReaderError:
401+
let n = r.parseValue(uint64)
402+
369403
test "nim v2 regression #23233":
370404
# Nim compiler bug #23233 will prevent
371405
# compilation if both JsonValueRef[uint64] and JsonValueRef[string]
372406
# are instantiated at together.
373407
var r1 = toReader(jsonText)
374408
let n1 = r1.parseValue(uint64)
375-
discard n1
409+
check n1["int"].numVal.integer == 789
376410

377411
var r2 = toReader(jsonText)
378412
let n2 = r2.parseValue(string)
379-
discard n2
413+
check n2["int"].numVal.integer == "789"

0 commit comments

Comments
 (0)