mirror of
https://github.com/logos-storage/nim-serde.git
synced 2026-01-07 16:13: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 ./stdjson
|
||||||
import ./pragmas
|
import ./pragmas
|
||||||
import ./types
|
import ./types
|
||||||
|
import ./helpers
|
||||||
|
|
||||||
export parser
|
export parser
|
||||||
export chronicles except toJson
|
export chronicles except toJson
|
||||||
@ -124,25 +125,35 @@ proc fromJson*[T: distinct](_: type T, json: JsonNode): ?!T =
|
|||||||
success T(?T.distinctBase.fromJson(json))
|
success T(?T.distinctBase.fromJson(json))
|
||||||
|
|
||||||
proc fromJson*(T: typedesc[StUint or StInt], json: JsonNode): ?!T =
|
proc fromJson*(T: typedesc[StUint or StInt], json: JsonNode): ?!T =
|
||||||
expectJsonKind(T, JString, json)
|
expectJsonKind(T, {JString, JInt, JNull}, json)
|
||||||
let jsonStr = json.getStr
|
|
||||||
let prefix =
|
case json.kind
|
||||||
if jsonStr.len >= 2:
|
of JNull: # return 0, optional values are handled up the call stack
|
||||||
jsonStr[0 .. 1].toLowerAscii
|
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:
|
else:
|
||||||
jsonStr
|
catch parse(jsonStr, T)
|
||||||
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)
|
|
||||||
|
|
||||||
proc fromJson*[T](_: type Option[T], json: JsonNode): ?!Option[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)
|
return success(none T)
|
||||||
without val =? T.fromJson(json), error:
|
without val =? T.fromJson(json), error:
|
||||||
return failure(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
|
||||||
import pkg/questionable/results
|
import pkg/questionable/results
|
||||||
import pkg/stew/byteutils
|
import pkg/stew/byteutils
|
||||||
|
import pkg/stint
|
||||||
|
|
||||||
suite "json - deserialize objects":
|
suite "json - deserialize objects":
|
||||||
test "can deserialize json objects":
|
test "can deserialize json objects":
|
||||||
@ -165,3 +166,44 @@ suite "json - deserialize objects from string":
|
|||||||
}"""
|
}"""
|
||||||
|
|
||||||
check !(Option[MyObj].fromJson(myObjJson)) == expected
|
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":
|
test "deserializes UInt256 from an empty string":
|
||||||
check !UInt256.fromJson("") == 0.u256
|
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":
|
test "deserializes ?UInt256 from an empty JString":
|
||||||
let json = newJString("")
|
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":
|
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":
|
test "deserializes UInt256 from JString with no prefix":
|
||||||
let json = newJString("1")
|
let json = newJString("1")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user