Writer produce correct top-level or in-array optional elem when custom flavor omit optional fields
This commit is contained in:
parent
164a8bcbd5
commit
9c74b885ea
|
@ -27,7 +27,8 @@ proc writeValue*(writer: var JsonWriter, value: Option) {.raises: [IOError].} =
|
||||||
|
|
||||||
if value.isSome:
|
if value.isSome:
|
||||||
writer.writeValue value.get
|
writer.writeValue value.get
|
||||||
elif not flavorOmitsOptionalFields(Flavor):
|
elif not flavorOmitsOptionalFields(Flavor) or
|
||||||
|
writer.nesting != JsonNesting.WriteObject:
|
||||||
writer.writeValue JsonString("null")
|
writer.writeValue JsonString("null")
|
||||||
|
|
||||||
proc readValue*[T](reader: var JsonReader, value: var Option[T]) =
|
proc readValue*[T](reader: var JsonReader, value: var Option[T]) =
|
||||||
|
|
|
@ -31,7 +31,8 @@ proc writeValue*[T](
|
||||||
|
|
||||||
if value.isOk:
|
if value.isOk:
|
||||||
writer.writeValue value.get
|
writer.writeValue value.get
|
||||||
elif not flavorOmitsOptionalFields(Flavor):
|
elif not flavorOmitsOptionalFields(Flavor) or
|
||||||
|
writer.nesting != JsonNesting.WriteObject:
|
||||||
writer.writeValue JsonString("null")
|
writer.writeValue JsonString("null")
|
||||||
|
|
||||||
proc readValue*[T](reader: var JsonReader, value: var Result[T, void]) =
|
proc readValue*[T](reader: var JsonReader, value: var Result[T, void]) =
|
||||||
|
|
|
@ -22,12 +22,19 @@ type
|
||||||
RecordStarted
|
RecordStarted
|
||||||
AfterField
|
AfterField
|
||||||
|
|
||||||
|
JsonNesting* {.pure.} = enum
|
||||||
|
TopLevel
|
||||||
|
WriteObject
|
||||||
|
WriteArray
|
||||||
|
|
||||||
JsonWriter*[Flavor = DefaultFlavor] = object
|
JsonWriter*[Flavor = DefaultFlavor] = object
|
||||||
stream*: OutputStream
|
stream*: OutputStream
|
||||||
hasTypeAnnotations: bool
|
hasTypeAnnotations: bool
|
||||||
hasPrettyOutput*: bool # read-only
|
hasPrettyOutput*: bool # read-only
|
||||||
nestingLevel*: int # read-only
|
nestingLevel*: int # read-only
|
||||||
state: JsonWriterState
|
state: JsonWriterState
|
||||||
|
nesting: JsonNesting
|
||||||
|
prevNesting: seq[JsonNesting]
|
||||||
|
|
||||||
Json.setWriter JsonWriter,
|
Json.setWriter JsonWriter,
|
||||||
PreferredOutput = string
|
PreferredOutput = string
|
||||||
|
@ -38,7 +45,11 @@ func init*(W: type JsonWriter, stream: OutputStream,
|
||||||
hasPrettyOutput: pretty,
|
hasPrettyOutput: pretty,
|
||||||
hasTypeAnnotations: typeAnnotations,
|
hasTypeAnnotations: typeAnnotations,
|
||||||
nestingLevel: if pretty: 0 else: -1,
|
nestingLevel: if pretty: 0 else: -1,
|
||||||
state: RecordExpected)
|
state: RecordExpected,
|
||||||
|
nesting: JsonNesting.TopLevel)
|
||||||
|
|
||||||
|
func nesting*(w: JsonWriter): JsonNesting =
|
||||||
|
w.nesting
|
||||||
|
|
||||||
proc beginRecord*(w: var JsonWriter, T: type)
|
proc beginRecord*(w: var JsonWriter, T: type)
|
||||||
proc beginRecord*(w: var JsonWriter)
|
proc beginRecord*(w: var JsonWriter)
|
||||||
|
@ -90,6 +101,8 @@ template fieldWritten*(w: var JsonWriter) =
|
||||||
proc beginRecord*(w: var JsonWriter) =
|
proc beginRecord*(w: var JsonWriter) =
|
||||||
doAssert w.state == RecordExpected
|
doAssert w.state == RecordExpected
|
||||||
|
|
||||||
|
w.prevNesting.add w.nesting
|
||||||
|
w.nesting = JsonNesting.WriteObject
|
||||||
append '{'
|
append '{'
|
||||||
if w.hasPrettyOutput:
|
if w.hasPrettyOutput:
|
||||||
w.nestingLevel += 2
|
w.nestingLevel += 2
|
||||||
|
@ -109,12 +122,15 @@ proc endRecord*(w: var JsonWriter) =
|
||||||
indent()
|
indent()
|
||||||
|
|
||||||
append '}'
|
append '}'
|
||||||
|
w.nesting = w.prevNesting.pop()
|
||||||
|
|
||||||
template endRecordField*(w: var JsonWriter) =
|
template endRecordField*(w: var JsonWriter) =
|
||||||
endRecord(w)
|
endRecord(w)
|
||||||
w.state = AfterField
|
w.state = AfterField
|
||||||
|
|
||||||
iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
|
iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
|
||||||
|
w.prevNesting.add w.nesting
|
||||||
|
w.nesting = JsonNesting.WriteArray
|
||||||
append '['
|
append '['
|
||||||
|
|
||||||
if w.hasPrettyOutput:
|
if w.hasPrettyOutput:
|
||||||
|
@ -140,6 +156,7 @@ iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
|
||||||
indent()
|
indent()
|
||||||
|
|
||||||
append ']'
|
append ']'
|
||||||
|
w.nesting = w.prevNesting.pop()
|
||||||
|
|
||||||
proc writeIterable*(w: var JsonWriter, collection: auto) =
|
proc writeIterable*(w: var JsonWriter, collection: auto) =
|
||||||
mixin writeValue
|
mixin writeValue
|
||||||
|
|
|
@ -16,4 +16,5 @@ import
|
||||||
test_spec,
|
test_spec,
|
||||||
test_parser,
|
test_parser,
|
||||||
test_line_col,
|
test_line_col,
|
||||||
test_reader
|
test_reader,
|
||||||
|
test_writer
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
# json-serialization
|
||||||
|
# Copyright (c) 2024 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
# at your option.
|
||||||
|
# This file may not be copied, modified, or distributed except according to
|
||||||
|
# those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
unittest2,
|
||||||
|
../json_serialization/stew/results,
|
||||||
|
../json_serialization/std/options,
|
||||||
|
../json_serialization
|
||||||
|
|
||||||
|
createJsonFlavor YourJson,
|
||||||
|
omitOptionalFields = false
|
||||||
|
|
||||||
|
createJsonFlavor MyJson,
|
||||||
|
omitOptionalFields = true
|
||||||
|
|
||||||
|
suite "Test writer":
|
||||||
|
test "stdlib option top level some YourJson":
|
||||||
|
var val = some(123)
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "123"
|
||||||
|
|
||||||
|
test "stdlib option top level none YourJson":
|
||||||
|
var val = none(int)
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "null"
|
||||||
|
|
||||||
|
test "stdlib option top level some MyJson":
|
||||||
|
var val = some(123)
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "123"
|
||||||
|
|
||||||
|
test "stdlib option top level none MyJson":
|
||||||
|
var val = none(int)
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "null"
|
||||||
|
|
||||||
|
test "results option top level some YourJson":
|
||||||
|
var val = Opt.some(123)
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "123"
|
||||||
|
|
||||||
|
test "results option top level none YourJson":
|
||||||
|
var val = Opt.none(int)
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "null"
|
||||||
|
|
||||||
|
test "results option top level some MyJson":
|
||||||
|
var val = Opt.some(123)
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "123"
|
||||||
|
|
||||||
|
test "results option top level none MyJson":
|
||||||
|
var val = Opt.none(int)
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "null"
|
||||||
|
|
||||||
|
test "stdlib option array some YourJson":
|
||||||
|
var val = [some(123), some(345)]
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "[123,345]"
|
||||||
|
|
||||||
|
test "stdlib option array none YourJson":
|
||||||
|
var val = [some(123), none(int), some(777)]
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "[123,null,777]"
|
||||||
|
|
||||||
|
test "stdlib option array some MyJson":
|
||||||
|
var val = [some(123), some(345)]
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "[123,345]"
|
||||||
|
|
||||||
|
test "stdlib option array none MyJson":
|
||||||
|
var val = [some(123), none(int), some(777)]
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "[123,null,777]"
|
||||||
|
|
||||||
|
test "results option array some YourJson":
|
||||||
|
var val = [Opt.some(123), Opt.some(345)]
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "[123,345]"
|
||||||
|
|
||||||
|
test "results option array none YourJson":
|
||||||
|
var val = [Opt.some(123), Opt.none(int), Opt.some(777)]
|
||||||
|
let json = YourJson.encode(val)
|
||||||
|
check json == "[123,null,777]"
|
||||||
|
|
||||||
|
test "results option array some MyJson":
|
||||||
|
var val = [Opt.some(123), Opt.some(345)]
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "[123,345]"
|
||||||
|
|
||||||
|
test "results option array none MyJson":
|
||||||
|
var val = [Opt.some(123), Opt.none(int), Opt.some(777)]
|
||||||
|
let json = MyJson.encode(val)
|
||||||
|
check json == "[123,null,777]"
|
Loading…
Reference in New Issue