diff options
-rw-r--r-- | lib/pure/json.nim | 27 | ||||
-rw-r--r-- | tests/stdlib/tjsonmacro.nim | 25 |
2 files changed, 50 insertions, 2 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 90cf7b8c9..b057aa7c6 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -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] diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index af9633e9e..f9f94606c 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -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 \ No newline at end of file + 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 \ No newline at end of file |