jsonutils.toJson now serializes JsonNode as is by default (#18097)

* jsonutils.toJson now serializes JsonNode as is (without deep copy nor treating it as a regular ref object)

* JsonNodeMode
This commit is contained in:
Timothee Cour 2021-05-31 13:17:52 -07:00 • committed by GitHub
commit 369a7d1246
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 5 deletions

View file

@ -48,13 +48,18 @@ type
joptEnumOrd
joptEnumSymbol
joptEnumString
JsonNodeMode* = enum ## controls `toJson` for JsonNode types
joptJsonNodeAsRef ## returns the ref as is
joptJsonNodeAsCopy ## returns a deep copy of the JsonNode
joptJsonNodeAsObject ## treats JsonNode as a regular ref object
ToJsonOptions* = object
enumMode*: EnumMode
# xxx charMode
jsonNodeMode*: JsonNodeMode
# xxx charMode, etc
proc initToJsonOptions*(): ToJsonOptions =
## initializes `ToJsonOptions` with sane options.
ToJsonOptions(enumMode: joptEnumOrd)
ToJsonOptions(enumMode: joptEnumOrd, jsonNodeMode: joptJsonNodeAsRef)
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
@ -286,8 +291,15 @@ proc toJson*[T](a: T, opt = initToJsonOptions()): JsonNode =
result = newJArray()
for v in a.fields: result.add toJson(v, opt)
elif T is ref | ptr:
if system.`==`(a, nil): result = newJNull()
else: result = toJson(a[], opt)
template impl =
if system.`==`(a, nil): result = newJNull()
else: result = toJson(a[], opt)
when T is JsonNode:
case opt.jsonNodeMode
of joptJsonNodeAsRef: result = a
of joptJsonNodeAsCopy: result = copy(a)
of joptJsonNodeAsObject: impl()
else: impl()
elif T is array | seq | set:
result = newJArray()
for ai in a: result.add toJson(ai, opt)