Fix json serialization for cid and enums (#615)

* use str on JString types, `$` will preserve `"`

* Adding enum support

* deserialize cid test

* make enum descerializer public

* unify fromJson for objects and refs

* add enum descerialization testing
This commit is contained in:
Dmitriy Ryajov 2023-11-14 09:23:50 -06:00 committed by GitHub
parent 2396c4d76d
commit a1725594a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 22 deletions

View File

@ -65,6 +65,13 @@ template expectJsonKind(
) = ) =
expectJsonKind(expectedType, {expectedKind}, json) expectJsonKind(expectedType, {expectedKind}, json)
proc fromJson*(
T: type enum,
json: JsonNode
): ?!T =
expectJsonKind(string, JString, json)
catch parseEnum[T](json.str)
proc fromJson*( proc fromJson*(
_: type string, _: type string,
json: JsonNode json: JsonNode
@ -177,7 +184,7 @@ proc fromJson*(
json: JsonNode json: JsonNode
): ?!Cid = ): ?!Cid =
expectJsonKind(Cid, JString, json) expectJsonKind(Cid, JString, json)
Cid.init($json).mapFailure Cid.init(json.str).mapFailure
proc fromJson*[T]( proc fromJson*[T](
_: type seq[T], _: type seq[T],
@ -189,34 +196,16 @@ proc fromJson*[T](
arr.add(? T.fromJson(elem)) arr.add(? T.fromJson(elem))
success arr success arr
proc fromJson*[T: object]( proc fromJson*[T: ref object or object](
_: type T, _: type T,
json: JsonNode json: JsonNode
): ?!T = ): ?!T =
expectJsonKind(T, JObject, json) expectJsonKind(T, JObject, json)
var res = T.default var res = when type(T) is ref: T.new() else: T.default
# Leave this in, it's good for debugging:
# trace "deserializing object", to = $T, json
for name, value in fieldPairs(res):
if json{name} != nil:
without parsed =? type(value).fromJson(json{name}), e:
error "error deserializing field",
field = $T & "." & name,
json = json{name},
error = e.msg
return failure(e)
value = parsed
success(res)
proc fromJson*[T: ref object](
_: type T,
json: JsonNode
): ?!T =
expectJsonKind(T, JObject, json)
var res = T.new()
# Leave this in, it's good for debugging: # Leave this in, it's good for debugging:
# trace "deserializing object", to = $T, json # trace "deserializing object", to = $T, json
for name, value in fieldPairs(res[]): for name, value in fieldPairs(when type(T) is ref: res[] else: res):
if json{name} != nil: if json{name} != nil:
without parsed =? type(value).fromJson(json{name}), e: without parsed =? type(value).fromJson(json{name}), e:
error "error deserializing field", error "error deserializing field",

View File

@ -11,6 +11,7 @@ from pkg/codex/rest/json import RestPurchase
import pkg/codex/utils/json as utilsjson import pkg/codex/utils/json as utilsjson
import pkg/questionable import pkg/questionable
import pkg/questionable/results import pkg/questionable/results
import pkg/libp2p
import ../examples import ../examples
import ../helpers import ../helpers
@ -213,6 +214,10 @@ checksuite "json serialization":
}""".flatten }""".flatten
check request.toJson == expected check request.toJson == expected
test "deserialize enum":
let json = newJString($CidVersion.CIDv1)
check !CidVersion.fromJson(json) == CIDv1
test "deserializes UInt256 from non-hex string representation": test "deserializes UInt256 from non-hex string representation":
let json = newJString("100000") let json = newJString("100000")
check !UInt256.fromJson(json) == 100000.u256 check !UInt256.fromJson(json) == 100000.u256
@ -327,6 +332,14 @@ checksuite "json serialization":
check deserialized.mystring == expected.mystring check deserialized.mystring == expected.mystring
check deserialized.myint == expected.myint check deserialized.myint == expected.myint
test "deserializes Cid":
let
jCid = newJString("zdj7Wakya26ggQWkvMdHYFcPgZ7Qh2HdMooQDDFDHkk4uHS14")
cid = "zdj7Wakya26ggQWkvMdHYFcPgZ7Qh2HdMooQDDFDHkk4uHS14"
check:
!Cid.fromJson(jCid) == !Cid.init(cid).mapFailure
test "deserializes StorageRequest": test "deserializes StorageRequest":
check !StorageRequest.fromJson(requestJson) == request check !StorageRequest.fromJson(requestJson) == request