Add support for serialization flavors

This commit is contained in:
Zahary Karadjov 2021-03-18 13:01:06 +02:00
parent 7999d25225
commit 706eb5740e
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
3 changed files with 58 additions and 12 deletions

View File

@ -11,7 +11,7 @@ export
types, errors
type
JsonReader* = object
JsonReader*[Flavor = DefaultFlavor] = object
lexer*: JsonLexer
allowUnknownFields: bool
@ -176,7 +176,11 @@ proc parseJsonNode(r: var JsonReader): JsonNode =
r.lexer.next()
if r.lexer.tok != tkCurlyRi:
while r.lexer.tok == tkString:
r.readJsonNodeField(result.fields.mgetOrPut(r.lexer.strVal, nil))
r.readJsonNodeField(
try:
result.fields.mgetOrPut(r.lexer.strVal, nil)
except KeyError:
raiseAssert "mgetOrPut should never raise a KeyError")
if r.lexer.tok == tkComma:
r.lexer.next()
else:
@ -368,6 +372,7 @@ template isCharArray(v: auto): bool = false
proc readValue*[T](r: var JsonReader, value: var T)
{.raises: [SerializationError, IOError, Defect].} =
mixin readValue
type ReaderType = type r
let tok {.used.} = r.lexer.tok
@ -495,7 +500,7 @@ proc readValue*[T](r: var JsonReader, value: var T)
r.skipToken tkCurlyLe
when T.totalSerializedFields > 0:
let fields = T.fieldReadersTable(JsonReader)
let fields = T.fieldReadersTable(ReaderType)
var expectedFieldPos = 0
while r.lexer.tok == tkString:
when T is tuple:

View File

@ -9,7 +9,7 @@ type
RecordStarted
AfterField
JsonWriter* = object
JsonWriter*[Flavor = DefaultFlavor] = object
stream*: OutputStream
hasTypeAnnotations: bool
hasPrettyOutput*: bool # read-only
@ -19,13 +19,13 @@ type
export
JsonString
proc init*(T: type JsonWriter, stream: OutputStream,
pretty = false, typeAnnotations = false): T =
result.stream = stream
result.hasPrettyOutput = pretty
result.hasTypeAnnotations = typeAnnotations
result.nestingLevel = if pretty: 0 else: -1
result.state = RecordExpected
proc init*(W: type JsonWriter, stream: OutputStream,
pretty = false, typeAnnotations = false): W =
W(stream: stream,
hasPrettyOutput: pretty,
hasTypeAnnotations: typeAnnotations,
nestingLevel: if pretty: 0 else: -1,
state: RecordExpected)
proc beginRecord*(w: var JsonWriter, T: type)
proc beginRecord*(w: var JsonWriter)
@ -228,7 +228,7 @@ proc toJson*(v: auto, pretty = false, typeAnnotations = false): string =
mixin writeValue
var s = memoryOutput()
var w = JsonWriter.init(s, pretty, typeAnnotations)
var w = JsonWriter[DefaultFlavor].init(s, pretty, typeAnnotations)
w.writeValue v
return s.getOutput(string)

View File

@ -0,0 +1,41 @@
import
strutils,
serialization,
../json_serialization
Json.createFlavor StringyJson
proc writeValue*(w: var JsonWriter[StringyJson], val: SomeInteger) =
writeValue(w, $val)
proc readValue*(r: var JsonReader[StringyJson], v: var SomeSignedInt) =
try:
v = type(v) parseBiggestInt readValue(r, string)
except ValueError as err:
r.raiseUnexpectedValue("A signed integer encoded as string")
proc readValue*(r: var JsonReader[StringyJson], v: var SomeUnsignedInt) =
try:
v = type(v) parseBiggestUInt readValue(r, string)
except ValueError as err:
r.raiseUnexpectedValue("An unsigned integer encoded as string")
type
Container = object
name: string
x: int
y: uint64
list: seq[int64]
let c = Container(name: "c", x: -10, y: 20, list: @[1'i64, 2, 25])
let encoded = StringyJson.encode(c)
echo "Encoded: ", encoded
let decoded = try:
StringyJson.decode(encoded, Container)
except SerializationError as err:
echo err.formatMsg("<encoded>")
quit 1
echo "Decoded: ", decoded