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:
|
||||
writer.writeValue value.get
|
||||
elif not flavorOmitsOptionalFields(Flavor):
|
||||
elif not flavorOmitsOptionalFields(Flavor) or
|
||||
writer.nesting != JsonNesting.WriteObject:
|
||||
writer.writeValue JsonString("null")
|
||||
|
||||
proc readValue*[T](reader: var JsonReader, value: var Option[T]) =
|
||||
|
|
|
@ -31,7 +31,8 @@ proc writeValue*[T](
|
|||
|
||||
if value.isOk:
|
||||
writer.writeValue value.get
|
||||
elif not flavorOmitsOptionalFields(Flavor):
|
||||
elif not flavorOmitsOptionalFields(Flavor) or
|
||||
writer.nesting != JsonNesting.WriteObject:
|
||||
writer.writeValue JsonString("null")
|
||||
|
||||
proc readValue*[T](reader: var JsonReader, value: var Result[T, void]) =
|
||||
|
|
|
@ -22,12 +22,19 @@ type
|
|||
RecordStarted
|
||||
AfterField
|
||||
|
||||
JsonNesting* {.pure.} = enum
|
||||
TopLevel
|
||||
WriteObject
|
||||
WriteArray
|
||||
|
||||
JsonWriter*[Flavor = DefaultFlavor] = object
|
||||
stream*: OutputStream
|
||||
hasTypeAnnotations: bool
|
||||
hasPrettyOutput*: bool # read-only
|
||||
nestingLevel*: int # read-only
|
||||
state: JsonWriterState
|
||||
nesting: JsonNesting
|
||||
prevNesting: seq[JsonNesting]
|
||||
|
||||
Json.setWriter JsonWriter,
|
||||
PreferredOutput = string
|
||||
|
@ -38,7 +45,11 @@ func init*(W: type JsonWriter, stream: OutputStream,
|
|||
hasPrettyOutput: pretty,
|
||||
hasTypeAnnotations: typeAnnotations,
|
||||
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)
|
||||
|
@ -90,6 +101,8 @@ template fieldWritten*(w: var JsonWriter) =
|
|||
proc beginRecord*(w: var JsonWriter) =
|
||||
doAssert w.state == RecordExpected
|
||||
|
||||
w.prevNesting.add w.nesting
|
||||
w.nesting = JsonNesting.WriteObject
|
||||
append '{'
|
||||
if w.hasPrettyOutput:
|
||||
w.nestingLevel += 2
|
||||
|
@ -109,12 +122,15 @@ proc endRecord*(w: var JsonWriter) =
|
|||
indent()
|
||||
|
||||
append '}'
|
||||
w.nesting = w.prevNesting.pop()
|
||||
|
||||
template endRecordField*(w: var JsonWriter) =
|
||||
endRecord(w)
|
||||
w.state = AfterField
|
||||
|
||||
iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
|
||||
w.prevNesting.add w.nesting
|
||||
w.nesting = JsonNesting.WriteArray
|
||||
append '['
|
||||
|
||||
if w.hasPrettyOutput:
|
||||
|
@ -140,6 +156,7 @@ iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
|
|||
indent()
|
||||
|
||||
append ']'
|
||||
w.nesting = w.prevNesting.pop()
|
||||
|
||||
proc writeIterable*(w: var JsonWriter, collection: auto) =
|
||||
mixin writeValue
|
||||
|
|
|
@ -16,4 +16,5 @@ import
|
|||
test_spec,
|
||||
test_parser,
|
||||
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