Don't write empty optional fields (#47)

This commit is contained in:
zah 2022-06-16 17:14:00 +03:00 committed by GitHub
parent 5034fef8d0
commit b9af0be99d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 8 deletions

View File

@ -1,6 +1,13 @@
import std/options, ../../json_serialization/[reader, writer, lexer] import std/options, ../../json_serialization/[reader, writer, lexer]
export options export options
template writeField*(w: var JsonWriter,
fieldName: static string,
field: Option,
record: auto) =
if field.isSome:
writeField(w, fieldName, field.get, record)
proc writeValue*(writer: var JsonWriter, value: Option) = proc writeValue*(writer: var JsonWriter, value: Option) =
if value.isSome: if value.isSome:
writer.writeValue value.get writer.writeValue value.get
@ -14,4 +21,3 @@ proc readValue*[T](reader: var JsonReader, value: var Option[T]) =
reader.lexer.next() reader.lexer.next()
else: else:
value = some reader.readValue(T) value = some reader.readValue(T)

View File

@ -0,0 +1,26 @@
import
stew/results, ../../json_serialization/[reader, writer, lexer]
export
results
template writeField*[T](w: var JsonWriter,
fieldName: static string,
field: Result[T, void],
record: auto) =
if field.isOk:
writeField(w, fieldName, field.get, record)
proc writeValue*[T](writer: var JsonWriter, value: Result[T, void]) =
if value.isOk:
writer.writeValue value.get
else:
writer.writeValue JsonString("null")
proc readValue*[T](reader: var JsonReader, value: var Result[T, void]) =
let tok = reader.lexer.lazyTok
if tok == tkNull:
reset value
reader.lexer.next()
else:
value.ok reader.readValue(T)

View File

@ -142,8 +142,21 @@ template isStringLike(v: string|cstring|openArray[char]|seq[char]): bool = true
template isStringLike[N](v: array[N, char]): bool = true template isStringLike[N](v: array[N, char]): bool = true
template isStringLike(v: auto): bool = false template isStringLike(v: auto): bool = false
template writeField*[FieldType, RecordType](w: var JsonWriter,
fieldName: static string,
field: FieldType,
record: RecordType) =
mixin writeFieldIMPL
type
F = type field
R = type record
w.writeFieldName(fieldName)
w.writeFieldIMPL(FieldTag[R, fieldName, F], field, record)
proc writeValue*(w: var JsonWriter, value: auto) = proc writeValue*(w: var JsonWriter, value: auto) =
mixin enumInstanceSerializedFields, writeValue, writeFieldIMPL mixin enumInstanceSerializedFields, writeValue
when value is JsonNode: when value is JsonNode:
append if w.hasPrettyOutput: value.pretty append if w.hasPrettyOutput: value.pretty
@ -216,12 +229,11 @@ proc writeValue*(w: var JsonWriter, value: auto) =
w.writeArray(value) w.writeArray(value)
elif value is (object or tuple): elif value is (object or tuple):
w.beginRecord(type(value))
type RecordType = type value type RecordType = type value
w.beginRecord RecordType
value.enumInstanceSerializedFields(fieldName, field): value.enumInstanceSerializedFields(fieldName, field):
type FieldType = type field mixin writeField
w.writeFieldName(fieldName) writeField(w, fieldName, field, value)
w.writeFieldIMPL(FieldTag[RecordType, fieldName, FieldType], field, value)
w.state = AfterField w.state = AfterField
w.endRecord() w.endRecord()

View File

@ -4,7 +4,8 @@ import
serialization/testing/generic_suite, serialization/testing/generic_suite,
../json_serialization, ./utils, ../json_serialization, ./utils,
../json_serialization/lexer, ../json_serialization/lexer,
../json_serialization/std/[options, sets, tables] ../json_serialization/std/[options, sets, tables],
../json_serialization/stew/results
type type
Foo = object Foo = object
@ -72,6 +73,10 @@ type
entry, exit: TokKind entry, exit: TokKind
dup: bool dup: bool
HoldsResultOpt* = object
r*: ref Simple
o*: Opt[Simple]
var var
customVisit: TokenRegistry customVisit: TokenRegistry
@ -327,7 +332,15 @@ suite "toJson tests":
h2 = HoldsOption(r: newSimple(1, "2", Meter(3))) h2 = HoldsOption(r: newSimple(1, "2", Meter(3)))
Json.roundtripTest h1, """{"r":null,"o":{"distance":3,"x":1,"y":"2"}}""" Json.roundtripTest h1, """{"r":null,"o":{"distance":3,"x":1,"y":"2"}}"""
Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"},"o":null}""" Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"}}"""
test "Result Opt types":
let
h1 = HoldsResultOpt(o: Opt[Simple].ok Simple(x: 1, y: "2", distance: Meter(3)))
h2 = HoldsResultOpt(r: newSimple(1, "2", Meter(3)))
Json.roundtripTest h1, """{"r":null,"o":{"distance":3,"x":1,"y":"2"}}"""
Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"}}"""
test "Case object as field": test "Case object as field":
let let