diff options
-rw-r--r-- | lib/pure/json.nim | 57 | ||||
-rw-r--r-- | tests/stdlib/tjsonmacro.nim | 18 |
2 files changed, 53 insertions, 22 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 1b887a0c5..b9f49f0bd 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1524,26 +1524,34 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] = doAssert result.len > 0 -proc processObjFields(obj: NimNode, - jsonNode: NimNode): seq[NimNode] {.compileTime.} = +proc processFields(obj: NimNode, + jsonNode: NimNode): seq[NimNode] {.compileTime.} = ## Process all the fields of an ``ObjectTy`` and any of its ## parent type's fields (via inheritance). result = @[] - - expectKind(obj[2], nnkRecList) - for field in obj[2]: - let nodes = processObjField(field, jsonNode) - result.add(nodes) - - # process parent type fields - case obj[1].kind - of nnkBracketExpr: - assert $obj[1][0] == "ref" - result.add(processObjFields(getType(obj[1][1]), jsonNode)) - of nnkSym: - result.add(processObjFields(getType(obj[1]), jsonNode)) + case obj.kind + of nnkObjectTy: + expectKind(obj[2], nnkRecList) + for field in obj[2]: + let nodes = processObjField(field, jsonNode) + result.add(nodes) + + # process parent type fields + case obj[1].kind + of nnkBracketExpr: + assert $obj[1][0] == "ref" + result.add(processFields(getType(obj[1][1]), jsonNode)) + of nnkSym: + result.add(processFields(getType(obj[1]), jsonNode)) + else: + discard + of nnkTupleTy: + for identDefs in obj: + expectKind(identDefs, nnkIdentDefs) + let nodes = processObjField(identDefs[0], jsonNode) + result.add(nodes) else: - discard + doAssert false, "Unable to process field type: " & $obj.kind proc processType(typeName: NimNode, obj: NimNode, jsonNode: NimNode, isRef: bool): NimNode {.compileTime.} = @@ -1558,13 +1566,17 @@ proc processType(typeName: NimNode, obj: NimNode, ## RecList ## Sym "events" case obj.kind - of nnkObjectTy: + of nnkObjectTy, nnkTupleTy: # Create object constructor. - result = newNimNode(nnkObjConstr) - result.add(typeName) # Name of the type to construct. + result = + if obj.kind == nnkObjectTy: newNimNode(nnkObjConstr) + else: newNimNode(nnkPar) + + if obj.kind == nnkObjectTy: + result.add(typeName) # Name of the type to construct. - # Process each object field and add it as an exprColonExpr - result.add(processObjFields(obj, jsonNode)) + # Process each object/tuple field and add it as an exprColonExpr + result.add(processFields(obj, jsonNode)) # Object might be null. So we need to check for that. if isRef: @@ -1687,6 +1699,8 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = result = createConstructor(obj, jsonNode) else: result = processType(typeSym, obj, jsonNode, false) + of nnkTupleTy: + result = processType(typeSym, typeSym, jsonNode, false) else: doAssert false, "Unable to create constructor for: " & $typeSym.kind @@ -1818,6 +1832,7 @@ macro to*(node: JsonNode, T: typedesc): untyped = # TODO: Rename postProcessValue and move it (?) result = postProcessValue(result) + # echo(treeRepr(result)) # echo(toStrLit(result)) when false: diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 2d20063ab..388d4d534 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -259,4 +259,20 @@ when isMainModule: let data = %*{"name": "foo", "challenge": "bar"} let msg = data.to(MsgChallenge) doAssert msg.name == "foo" - doAssert msg.challenge == "bar" \ No newline at end of file + doAssert msg.challenge == "bar" + + block: + type + Color = enum Red, Brown + Thing = object + animal: tuple[fur: bool, legs: int] + color: Color + + var j = parseJson(""" + {"animal":{"fur":true,"legs":6},"color":"Red"} + """) + + let parsed = to(j, Thing) + doAssert parsed.animal.fur + doAssert parsed.animal.legs == 6 + doAssert parsed.color == Red \ No newline at end of file |