mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 13:30:33 +00:00
Implement support for Option[T] in json.to macro. Fixes #5848.
This commit is contained in:
committed by
Dominik Picheta
parent
d3c9b58c00
commit
8ca41ce637
@@ -1346,6 +1346,16 @@ proc createJsonIndexer(jsonNode: NimNode,
|
||||
indexNode
|
||||
)
|
||||
|
||||
proc transformJsonIndexer(jsonNode: NimNode): NimNode =
|
||||
case jsonNode.kind
|
||||
of nnkBracketExpr:
|
||||
result = newNimNode(nnkCurlyExpr)
|
||||
else:
|
||||
result = jsonNode.copy()
|
||||
|
||||
for child in jsonNode:
|
||||
result.add(transformJsonIndexer(child))
|
||||
|
||||
template verifyJsonKind(node: JsonNode, kinds: set[JsonNodeKind],
|
||||
ast: string) =
|
||||
if node.kind notin kinds:
|
||||
@@ -1637,6 +1647,10 @@ proc processType(typeName: NimNode, obj: NimNode,
|
||||
|
||||
doAssert(not result.isNil(), "processType not initialised.")
|
||||
|
||||
import options
|
||||
proc workaroundMacroNone[T](): Option[T] =
|
||||
none(T)
|
||||
|
||||
proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
|
||||
## Accepts a type description, i.e. "ref Type", "seq[Type]", "Type" etc.
|
||||
##
|
||||
@@ -1650,6 +1664,19 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
|
||||
of nnkBracketExpr:
|
||||
var bracketName = ($typeSym[0]).normalize
|
||||
case bracketName
|
||||
of "option":
|
||||
# TODO: Would be good to verify that this is Option[T] from
|
||||
# options module I suppose.
|
||||
let lenientJsonNode = transformJsonIndexer(jsonNode)
|
||||
|
||||
let optionGeneric = typeSym[1]
|
||||
let value = createConstructor(typeSym[1], jsonNode)
|
||||
let workaround = bindSym("workaroundMacroNone") # TODO: Nim Bug: This shouldn't be necessary.
|
||||
|
||||
result = quote do:
|
||||
(
|
||||
if `lenientJsonNode`.isNil: `workaround`[`optionGeneric`]() else: some[`optionGeneric`](`value`)
|
||||
)
|
||||
of "ref":
|
||||
# Ref type.
|
||||
var typeName = $typeSym[1]
|
||||
|
||||
@@ -2,7 +2,7 @@ discard """
|
||||
file: "tjsonmacro.nim"
|
||||
output: ""
|
||||
"""
|
||||
import json, strutils
|
||||
import json, strutils, options
|
||||
|
||||
when isMainModule:
|
||||
# Tests inspired by own use case (with some additional tests).
|
||||
@@ -295,4 +295,25 @@ when isMainModule:
|
||||
let parsed = mulTest().to(Car)
|
||||
doAssert parsed.engine.name == "V8"
|
||||
|
||||
doAssert i == 1
|
||||
doAssert i == 1
|
||||
|
||||
block:
|
||||
# Option[T] support!
|
||||
type
|
||||
Car1 = object # TODO: Codegen bug when `Car`
|
||||
engine: tuple[name: string, capacity: Option[float]]
|
||||
model: string
|
||||
year: Option[int]
|
||||
|
||||
let noYear = """
|
||||
{"engine": {"name": "V8", "capacity": 5.5}, "model": "Skyline"}
|
||||
"""
|
||||
|
||||
let noYearParsed = parseJson(noYear)
|
||||
let noYearDeser = to(noYearParsed, Car1)
|
||||
doAssert noYearDeser.engine.capacity == some(5.5)
|
||||
doAssert noYearDeser.year.isNone
|
||||
doAssert noYearDeser.engine.name == "V8"
|
||||
|
||||
# TODO: Table[T, Y] support.
|
||||
# TODO: JsonNode support
|
||||
Reference in New Issue
Block a user