mirror of
https://github.com/logos-storage/nim-serde.git
synced 2026-01-02 13:43:06 +00:00
feat: improve stint parsing (#22)
- change empty string value to none when optional - handle null, "null", JNull, seq[stint], seq[?string]
This commit is contained in:
parent
d84641333a
commit
6d2fc9406a
@ -16,6 +16,7 @@ import ./errors
|
||||
import ./stdjson
|
||||
import ./pragmas
|
||||
import ./types
|
||||
import ./helpers
|
||||
|
||||
export parser
|
||||
export chronicles except toJson
|
||||
@ -124,25 +125,35 @@ proc fromJson*[T: distinct](_: type T, json: JsonNode): ?!T =
|
||||
success T(?T.distinctBase.fromJson(json))
|
||||
|
||||
proc fromJson*(T: typedesc[StUint or StInt], json: JsonNode): ?!T =
|
||||
expectJsonKind(T, JString, json)
|
||||
let jsonStr = json.getStr
|
||||
let prefix =
|
||||
if jsonStr.len >= 2:
|
||||
jsonStr[0 .. 1].toLowerAscii
|
||||
expectJsonKind(T, {JString, JInt, JNull}, json)
|
||||
|
||||
case json.kind
|
||||
of JNull: # return 0, optional values are handled up the call stack
|
||||
return catch parse("0", T)
|
||||
of JInt:
|
||||
return catch parse($json, T)
|
||||
else: # JString (only other kind allowed)
|
||||
if json.isNullString:
|
||||
return catch parse("0", T)
|
||||
|
||||
let jsonStr = json.getStr
|
||||
let prefix =
|
||||
if jsonStr.len >= 2:
|
||||
jsonStr[0 .. 1].toLowerAscii
|
||||
else:
|
||||
jsonStr
|
||||
case prefix
|
||||
of "0x":
|
||||
catch parse(jsonStr, T, 16)
|
||||
of "0o":
|
||||
catch parse(jsonStr, T, 8)
|
||||
of "0b":
|
||||
catch parse(jsonStr, T, 2)
|
||||
else:
|
||||
jsonStr
|
||||
case prefix
|
||||
of "0x":
|
||||
catch parse(jsonStr, T, 16)
|
||||
of "0o":
|
||||
catch parse(jsonStr, T, 8)
|
||||
of "0b":
|
||||
catch parse(jsonStr, T, 2)
|
||||
else:
|
||||
catch parse(jsonStr, T)
|
||||
catch parse(jsonStr, T)
|
||||
|
||||
proc fromJson*[T](_: type Option[T], json: JsonNode): ?!Option[T] =
|
||||
if json.isNil or json.kind == JNull:
|
||||
if json.isNil or json.kind == JNull or json.isEmptyString or json.isNullString:
|
||||
return success(none T)
|
||||
without val =? T.fromJson(json), error:
|
||||
return failure(error)
|
||||
|
||||
7
serde/json/helpers.nim
Normal file
7
serde/json/helpers.nim
Normal file
@ -0,0 +1,7 @@
|
||||
import std/json
|
||||
|
||||
func isEmptyString*(json: JsonNode): bool =
|
||||
return json.kind == JString and json.getStr == ""
|
||||
|
||||
func isNullString*(json: JsonNode): bool =
|
||||
return json.kind == JString and json.getStr == "null"
|
||||
@ -3,6 +3,7 @@ import pkg/serde
|
||||
import pkg/questionable
|
||||
import pkg/questionable/results
|
||||
import pkg/stew/byteutils
|
||||
import pkg/stint
|
||||
|
||||
suite "json - deserialize objects":
|
||||
test "can deserialize json objects":
|
||||
@ -165,3 +166,44 @@ suite "json - deserialize objects from string":
|
||||
}"""
|
||||
|
||||
check !(Option[MyObj].fromJson(myObjJson)) == expected
|
||||
|
||||
test "deserializes object with UInt256 from string":
|
||||
type MyObj = object
|
||||
mystring: string
|
||||
myu256: UInt256
|
||||
|
||||
let expected = MyObj(mystring: "abc", myu256: 1.u256)
|
||||
let myObjJson =
|
||||
"""{
|
||||
"mystring": "abc",
|
||||
"myu256": 1
|
||||
}"""
|
||||
|
||||
check !MyObj.fromJson(myObjJson) == expected
|
||||
|
||||
test "deserializes object with stringified UInt256 from string":
|
||||
type MyObj = object
|
||||
mystring: string
|
||||
myu256: UInt256
|
||||
|
||||
let expected = MyObj(mystring: "abc", myu256: 1.u256)
|
||||
let myObjJson =
|
||||
"""{
|
||||
"mystring": "abc",
|
||||
"myu256": "1"
|
||||
}"""
|
||||
|
||||
check !MyObj.fromJson(myObjJson) == expected
|
||||
|
||||
test "deserializes object with ?UInt256 from string":
|
||||
type MyObj = object
|
||||
mystring: string
|
||||
myu256: ?UInt256
|
||||
|
||||
let expected = MyObj(mystring: "abc", myu256: UInt256.none)
|
||||
let myObjJson =
|
||||
"""{
|
||||
"mystring": "abc",
|
||||
}"""
|
||||
|
||||
check !MyObj.fromJson(myObjJson) == expected
|
||||
|
||||
@ -13,12 +13,52 @@ suite "json - deserialize stint":
|
||||
test "deserializes UInt256 from an empty string":
|
||||
check !UInt256.fromJson("") == 0.u256
|
||||
|
||||
test "deserializes UInt256 from null string":
|
||||
check !UInt256.fromJson("null") == 0.u256
|
||||
|
||||
test "deserializes UInt256 from JNull":
|
||||
check !UInt256.fromJson(newJNull()) == 0.u256
|
||||
|
||||
test "deserializes ?UInt256 from an empty JString":
|
||||
let json = newJString("")
|
||||
check !Option[UInt256].fromJson(json) == 0.u256.some
|
||||
check !Option[UInt256].fromJson(json) == UInt256.none
|
||||
|
||||
test "deserializes ?UInt256 from an empty string":
|
||||
check !Option[UInt256].fromJson("") == 0.u256.some
|
||||
check !Option[UInt256].fromJson("") == UInt256.none
|
||||
|
||||
test "deserializes ?UInt256 from null string":
|
||||
check !Option[UInt256].fromJson("null") == UInt256.none
|
||||
|
||||
test "deserializes ?UInt256 from JNull":
|
||||
check !Option[UInt256].fromJson(newJNull()) == UInt256.none
|
||||
|
||||
test "deserializes seq[UInt256] from string":
|
||||
check seq[UInt256].fromJson("[1,2,3]") == success @[1.u256, 2.u256, 3.u256]
|
||||
|
||||
test "deserializes seq[UInt256] from string with empty string item":
|
||||
check seq[UInt256].fromJson("[1,2,\"\"]") == success @[1.u256, 2.u256, 0.u256]
|
||||
|
||||
test "deserializes seq[UInt256] from string with null item":
|
||||
check seq[UInt256].fromJson("[1,2,null]") == success @[1.u256, 2.u256, 0.u256]
|
||||
|
||||
test "deserializes seq[UInt256] from string with null string item":
|
||||
check seq[UInt256].fromJson("[1,2,\"null\"]") == success @[1.u256, 2.u256, 0.u256]
|
||||
|
||||
test "deserializes seq[?UInt256] from string":
|
||||
check seq[?UInt256].fromJson("[1,2,3]") ==
|
||||
success @[1.u256.some, 2.u256.some, 3.u256.some]
|
||||
|
||||
test "deserializes seq[?UInt256] from string with empty string item":
|
||||
check seq[?UInt256].fromJson("[1,2,\"\"]") ==
|
||||
success @[1.u256.some, 2.u256.some, UInt256.none]
|
||||
|
||||
test "deserializes seq[?UInt256] from string with null item":
|
||||
check seq[?UInt256].fromJson("[1,2,null]") ==
|
||||
success @[1.u256.some, 2.u256.some, UInt256.none]
|
||||
|
||||
test "deserializes seq[?UInt256] from string with null string item":
|
||||
check seq[?UInt256].fromJson("[1,2,\"null\"]") ==
|
||||
success @[1.u256.some, 2.u256.some, UInt256.none]
|
||||
|
||||
test "deserializes UInt256 from JString with no prefix":
|
||||
let json = newJString("1")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user