Don't write empty optional fields (#47)
This commit is contained in:
parent
5034fef8d0
commit
b9af0be99d
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue