Add JsonVoid, JsonNumber, and JsonValueRef to JsonWriter

This commit is contained in:
jangko 2023-12-27 11:50:26 +07:00
parent 9720b33f99
commit 61a03e20d3
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 102 additions and 8 deletions

View File

@ -162,15 +162,12 @@ template writeObjectField*[FieldType, RecordType](w: var JsonWriter,
field: FieldType): bool = field: FieldType): bool =
mixin writeFieldIMPL, writeValue mixin writeFieldIMPL, writeValue
type
R {.used.} = type record
w.writeFieldName(fieldName) w.writeFieldName(fieldName)
when RecordType is tuple: when RecordType is tuple:
w.writeValue(field) w.writeValue(field)
else: else:
type RR = type record type R = type record
w.writeFieldIMPL(FieldTag[RR, fieldName], field, record) w.writeFieldIMPL(FieldTag[R, fieldName], field, record)
true true
proc writeRecordValue*(w: var JsonWriter, value: auto) proc writeRecordValue*(w: var JsonWriter, value: auto)
@ -179,11 +176,67 @@ proc writeRecordValue*(w: var JsonWriter, value: auto)
type RecordType = type value type RecordType = type value
w.beginRecord RecordType w.beginRecord RecordType
value.enumInstanceSerializedFields(fieldName, field): value.enumInstanceSerializedFields(fieldName, fieldType):
if writeObjectField(w, value, fieldName, field): when fieldType isnot JsonVoid:
w.state = AfterField if writeObjectField(w, value, fieldName, fieldType):
w.state = AfterField
w.endRecord() w.endRecord()
proc writeNumber*[F,T](w: var JsonWriter[F], value: JsonNumber[T]) =
if value.sign == JsonSign.Neg:
append '-'
when T is uint64:
w.stream.writeText value.integer
else:
append value.integer
if value.fraction.len > 0:
append '.'
append value.fraction
template writeExp(body: untyped) =
when T is uint64:
if value.exponent > 0:
body
else:
if value.exponent.len > 0:
body
writeExp:
append 'e'
if value.sign == JsonSign.Neg:
append '-'
when T is uint64:
w.stream.writeText value.exponent
else:
append value.exponent
proc writeJsonValueRef*[F,T](w: var JsonWriter[F], value: JsonValueRef[T]) =
if value.isNil:
append "null"
return
case value.kind
of JsonValueKind.String:
w.writeValue(value.strVal)
of JsonValueKind.Number:
w.writeNumber(value.numVal)
of JsonValueKind.Object:
w.beginRecord typeof(value)
for k, v in value.objVal:
w.writeField(k, v)
w.endRecord()
of JsonValueKind.Array:
w.writeArray(value.arrayVal)
of JsonValueKind.Bool:
if value.boolVal:
append "true"
else:
append "false"
of JsonValueKind.Null:
append "null"
proc writeValue*(w: var JsonWriter, value: auto) {.gcsafe, raises: [IOError].} = proc writeValue*(w: var JsonWriter, value: auto) {.gcsafe, raises: [IOError].} =
mixin writeValue mixin writeValue
@ -194,6 +247,15 @@ proc writeValue*(w: var JsonWriter, value: auto) {.gcsafe, raises: [IOError].} =
elif value is JsonString: elif value is JsonString:
append string(value) append string(value)
elif value is JsonVoid:
discard
elif value is JsonNumber:
w.writeNumber(value)
elif value is JsonValueRef:
w.writeJsonValueRef(value)
elif value is ref: elif value is ref:
if value == nil: if value == nil:
append "null" append "null"

View File

@ -45,11 +45,34 @@ type
one: Opt[string] one: Opt[string]
two: Option[int] two: Option[int]
SpecialTypes = object
one: JsonVoid
two: JsonNumber[uint64]
three: JsonNumber[string]
four: JsonValueRef[uint64]
Container.useDefaultSerializationIn StringyJson Container.useDefaultSerializationIn StringyJson
createJsonFlavor OptJson createJsonFlavor OptJson
OptionalFields.useDefaultSerializationIn OptJson OptionalFields.useDefaultSerializationIn OptJson
const
jsonText = """
{
"one": "this text will gone",
"two": -789.0009E-19,
"three": 999.776000E+33,
"four" : {
"apple": [1, true, "three"],
"banana": {
"chip": 123,
"z": null,
"v": false
}
}
}
"""
suite "Test JsonFlavor": suite "Test JsonFlavor":
test "basic test": test "basic test":
let c = Container(name: "c", x: -10, y: 20, list: @[1'i64, 2, 25]) let c = Container(name: "c", x: -10, y: 20, list: @[1'i64, 2, 25])
@ -72,3 +95,12 @@ suite "Test JsonFlavor":
let cc = OptJson.encode(c) let cc = OptJson.encode(c)
check cc == """{"one":"burn","two":333}""" check cc == """{"one":"burn","two":333}"""
test "Write special types":
let vv = Json.decode(jsonText, SpecialTypes)
let xx = Json.encode(vv)
var ww = Json.decode(xx, SpecialTypes)
ww.three.expSign = JsonSign.Pos # the rest of it should identical to vv
check:
ww == vv
xx == """{"two":-789.0009e-19,"three":999.776000e33,"four":{"apple":[1,true,"three"],"banana":{"chip":123,"z":null,"v":false}}}"""