Skip to content
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
23 changes: 16 additions & 7 deletions json_serialization/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import
./reader_desc,
./lexer

from json import JsonNode, JsonNodeKind, escapeJson
from json import JsonNode, JsonNodeKind, escapeJson, parseJson

export
reader_desc
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
38 changes: 36 additions & 2 deletions tests/test_parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,14 @@ const
}
}

"""

jsonBigNum = """
{
"bignum": 9999999999999999999999999999999999999999999,
"float": 124.123,
"int": -12345
}
"""

suite "Parse to runtime dynamic structure":
Expand All @@ -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
Expand All @@ -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"
Expand All @@ -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"