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:
parent
9559350e34
commit
369a7d1246
3 changed files with 41 additions and 5 deletions
|
|
@ -69,7 +69,9 @@
|
||||||
previous behavior for a transition time, see PR #17467.
|
previous behavior for a transition time, see PR #17467.
|
||||||
|
|
||||||
- `jsonutils` now serializes/deserializes holey enums as regular enums (via `ord`) instead of as strings.
|
- `jsonutils` now serializes/deserializes holey enums as regular enums (via `ord`) instead of as strings.
|
||||||
Use `-d:nimLegacyJsonutilsHoleyEnum` for a transition period.
|
Use `-d:nimLegacyJsonutilsHoleyEnum` for a transition period. `toJson` now serializes `JsonNode`
|
||||||
|
as is via reference (without a deep copy) instead of treating `JsonNode` as a regular ref object,
|
||||||
|
this can be customized via `jsonNodeMode`.
|
||||||
|
|
||||||
- `json` and `jsonutils` now serialize NaN, Inf, -Inf as strings, so that
|
- `json` and `jsonutils` now serialize NaN, Inf, -Inf as strings, so that
|
||||||
`%[NaN, -Inf]` is the string `["nan","-inf"]` instead of `[nan,-inf]` which was invalid json.
|
`%[NaN, -Inf]` is the string `["nan","-inf"]` instead of `[nan,-inf]` which was invalid json.
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,18 @@ type
|
||||||
joptEnumOrd
|
joptEnumOrd
|
||||||
joptEnumSymbol
|
joptEnumSymbol
|
||||||
joptEnumString
|
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
|
ToJsonOptions* = object
|
||||||
enumMode*: EnumMode
|
enumMode*: EnumMode
|
||||||
# xxx charMode
|
jsonNodeMode*: JsonNodeMode
|
||||||
|
# xxx charMode, etc
|
||||||
|
|
||||||
proc initToJsonOptions*(): ToJsonOptions =
|
proc initToJsonOptions*(): ToJsonOptions =
|
||||||
## initializes `ToJsonOptions` with sane options.
|
## initializes `ToJsonOptions` with sane options.
|
||||||
ToJsonOptions(enumMode: joptEnumOrd)
|
ToJsonOptions(enumMode: joptEnumOrd, jsonNodeMode: joptJsonNodeAsRef)
|
||||||
|
|
||||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||||
proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
|
proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
|
||||||
|
|
@ -286,8 +291,15 @@ proc toJson*[T](a: T, opt = initToJsonOptions()): JsonNode =
|
||||||
result = newJArray()
|
result = newJArray()
|
||||||
for v in a.fields: result.add toJson(v, opt)
|
for v in a.fields: result.add toJson(v, opt)
|
||||||
elif T is ref | ptr:
|
elif T is ref | ptr:
|
||||||
|
template impl =
|
||||||
if system.`==`(a, nil): result = newJNull()
|
if system.`==`(a, nil): result = newJNull()
|
||||||
else: result = toJson(a[], opt)
|
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:
|
elif T is array | seq | set:
|
||||||
result = newJArray()
|
result = newJArray()
|
||||||
for ai in a: result.add toJson(ai, opt)
|
for ai in a: result.add toJson(ai, opt)
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,28 @@ template fn() =
|
||||||
doAssert b2.ord == 1 # explains the `1`
|
doAssert b2.ord == 1 # explains the `1`
|
||||||
testRoundtrip(a): """[1,2,3]"""
|
testRoundtrip(a): """[1,2,3]"""
|
||||||
|
|
||||||
|
block: # JsonNode
|
||||||
|
let a = ((1, 2.5, "abc").toJson, (3, 4.5, "foo"))
|
||||||
|
testRoundtripVal(a): """[[1,2.5,"abc"],[3,4.5,"foo"]]"""
|
||||||
|
|
||||||
|
block:
|
||||||
|
template toInt(a): untyped = cast[int](a)
|
||||||
|
|
||||||
|
let a = 3.toJson
|
||||||
|
let b = (a, a)
|
||||||
|
|
||||||
|
let c1 = b.toJson
|
||||||
|
doAssert c1[0].toInt == a.toInt
|
||||||
|
doAssert c1[1].toInt == a.toInt
|
||||||
|
|
||||||
|
let c2 = b.toJson(ToJsonOptions(jsonNodeMode: joptJsonNodeAsCopy))
|
||||||
|
doAssert c2[0].toInt != a.toInt
|
||||||
|
doAssert c2[1].toInt != c2[0].toInt
|
||||||
|
doAssert c2[1] == c2[0]
|
||||||
|
|
||||||
|
let c3 = b.toJson(ToJsonOptions(jsonNodeMode: joptJsonNodeAsObject))
|
||||||
|
doAssert $c3 == """[{"isUnquoted":false,"kind":2,"num":3},{"isUnquoted":false,"kind":2,"num":3}]"""
|
||||||
|
|
||||||
block: # ToJsonOptions
|
block: # ToJsonOptions
|
||||||
let a = (me1, me2)
|
let a = (me1, me2)
|
||||||
doAssert $a.toJson() == "[1,2]"
|
doAssert $a.toJson() == "[1,2]"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue