Handle changes in the serialization APIs

This commit is contained in:
Zahary Karadjov 2019-07-08 10:57:05 +03:00
parent 7922a83c4d
commit 73d9e0d458
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
3 changed files with 30 additions and 23 deletions

View File

@ -17,10 +17,6 @@ type
encounteredField*: cstring
deserializedType*: cstring
CustomSerializationError* = object of JsonReaderError
deserializedField*: string
innerException*: ref CatchableError
ExpectedTokenCategory* = enum
etBool = "bool literal"
etInt = "integer"
@ -33,6 +29,10 @@ type
etCurrlyLe = "object start bracket"
etCurrlyRi = "object end bracket"
GenericJsonReaderError* = object of JsonReaderError
deserializedField*: string
innerException*: ref CatchableError
UnexpectedToken* = object of JsonReaderError
encountedToken*: TokKind
expectedToken*: ExpectedTokenCategory
@ -46,8 +46,8 @@ method formatMsg*(err: ref UnexpectedField, filename: string): string =
method formatMsg*(err: ref UnexpectedToken, filename: string): string =
fmt"{filename}({err.line}, {err.col}) Unexpected token '{err.encountedToken}' in place of '{err.expectedToken}'"
method formatMsg*(err: ref CustomSerializationError, filename: string): string =
fmt"{filename}({err.line}, {err.col}) Custom serialization exception while deserializing '{err.deserializedField}': [{err.innerException.name}] {err.innerException.msg}"
method formatMsg*(err: ref GenericJsonReaderError, filename: string): string =
fmt"{filename}({err.line}, {err.col}) Exception encountered while deserializing '{err.deserializedField}': [{err.innerException.name}] {err.innerException.msg}"
template init*(T: type JsonReader, stream: ByteStreamVar, mode = defaultJsonMode): auto =
init JsonReader, AsciiStreamVar(stream), mode
@ -70,10 +70,12 @@ proc raiseUnexpectedField(r: JsonReader, fieldName, deserializedType: cstring) =
ex.deserializedType = deserializedType
raise ex
proc readValueFailed*(r: JsonReader,
Record: type, fieldName: string, field: var auto,
err: ref CatchableError) =
var ex = new CustomSerializationError
proc handleReadException*(r: JsonReader,
Record: type,
fieldName: string,
field: var auto,
err: ref CatchableError) =
var ex = new GenericJsonReaderError
ex.assignLineNumber(r)
ex.deserializedField = fieldName
ex.innerException = err

View File

@ -125,6 +125,8 @@ proc writeArray[T](w: var JsonWriter, elements: openarray[T]) =
writeIterable(w, elements)
proc writeValue*(w: var JsonWriter, value: auto) =
mixin enumInstanceSerializedFields
template addChar(c) =
append c
@ -161,7 +163,6 @@ proc writeValue*(w: var JsonWriter, value: auto) =
# TODO: Should this really use a decimal representation?
# Or perhaps $ord(c) returns hex?
# This is potentially a bug in Nim's json module.
# In any case, we can call appendNumber here.
append $ord(c)
of '\\': addPrefixSlash '\\'
else: addChar c
@ -170,16 +171,16 @@ proc writeValue*(w: var JsonWriter, value: auto) =
elif value is bool:
append if value: "true" else: "false"
elif value is enum:
w.stream.appendNumber ord(value)
w.stream.append $ord(value)
elif value is SomeInteger:
w.stream.appendNumber value
w.stream.append $value
elif value is SomeFloat:
append $value
elif value is (seq or array):
w.writeArray(value)
elif value is (object or tuple):
w.beginRecord(type(value))
value.serializeFields(k, v):
value.enumInstanceSerializedFields(k, v):
w.writeField k, v
w.endRecord()
else:

View File

@ -1,5 +1,6 @@
import
strutils, unittest,
serialization/object_serialization,
serialization/testing/generic_suite,
../json_serialization, ./utils,
../json_serialization/std/[options, sets]
@ -12,10 +13,11 @@ type
x: int
y: string
distance: Meter
ignored: int
Foo = object
i: int
b: Bar
b {.dontSerialize.}: Bar
s: string
Bar = object
@ -41,6 +43,8 @@ template reject(code) =
borrowSerialization(Meter, int)
Simple.setSerializedFields distance, x, y
proc `==`(lhs, rhs: Meter): bool =
int(lhs) == int(rhs)
@ -74,21 +78,21 @@ suite "toJson tests":
var s = Simple(x: 10, y: "test", distance: Meter(20))
check:
s.toJson == """{"x":10,"y":"test","distance":20}"""
s.toJson(typeAnnotations = true) == """{"$type":"Simple","x":10,"y":"test","distance":20}"""
s.toJson == """{"distance":20,"x":10,"y":"test"}"""
s.toJson(typeAnnotations = true) == """{"$type":"Simple","distance":20,"x":10,"y":"test"}"""
s.toJson(pretty = true) == dedent"""
{
"distance": 20,
"x": 10,
"y": "test",
"distance": 20
"y": "test"
}
"""
test "handle missing fields":
let json = dedent"""
{
"y": "test",
"distance": 20
"distance": 20,
"y": "test"
}
"""
@ -135,8 +139,8 @@ suite "toJson tests":
h1 = HoldsOption(o: some Simple(x: 1, y: "2", distance: Meter(3)))
h2 = HoldsOption(r: newSimple(1, "2", Meter(3)))
Json.roundtripTest h1, """{"r":null,"o":{"x":1,"y":"2","distance":3}}"""
Json.roundtripTest h2, """{"r":{"x":1,"y":"2","distance":3},"o":null}"""
Json.roundtripTest h1, """{"r":null,"o":{"distance":3,"x":1,"y":"2"}}"""
Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"},"o":null}"""
test "Set types":
type HoldsSet = object