This commit is contained in:
Dominik Picheta 2017-11-29 14:48:17 +00:00 • committed by Dominik Picheta
commit e0681715dc
2 changed files with 52 additions and 21 deletions

View file

@ -1524,26 +1524,34 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
doAssert result.len > 0 doAssert result.len > 0
proc processObjFields(obj: NimNode, proc processFields(obj: NimNode,
jsonNode: NimNode): seq[NimNode] {.compileTime.} = jsonNode: NimNode): seq[NimNode] {.compileTime.} =
## Process all the fields of an ``ObjectTy`` and any of its ## Process all the fields of an ``ObjectTy`` and any of its
## parent type's fields (via inheritance). ## parent type's fields (via inheritance).
result = @[] result = @[]
case obj.kind
of nnkObjectTy:
expectKind(obj[2], nnkRecList)
for field in obj[2]:
let nodes = processObjField(field, jsonNode)
result.add(nodes)
expectKind(obj[2], nnkRecList) # process parent type fields
for field in obj[2]: case obj[1].kind
let nodes = processObjField(field, jsonNode) of nnkBracketExpr:
result.add(nodes) assert $obj[1][0] == "ref"
result.add(processFields(getType(obj[1][1]), jsonNode))
# process parent type fields of nnkSym:
case obj[1].kind result.add(processFields(getType(obj[1]), jsonNode))
of nnkBracketExpr: else:
assert $obj[1][0] == "ref" discard
result.add(processObjFields(getType(obj[1][1]), jsonNode)) of nnkTupleTy:
of nnkSym: for identDefs in obj:
result.add(processObjFields(getType(obj[1]), jsonNode)) expectKind(identDefs, nnkIdentDefs)
let nodes = processObjField(identDefs[0], jsonNode)
result.add(nodes)
else: else:
discard doAssert false, "Unable to process field type: " & $obj.kind
proc processType(typeName: NimNode, obj: NimNode, proc processType(typeName: NimNode, obj: NimNode,
jsonNode: NimNode, isRef: bool): NimNode {.compileTime.} = jsonNode: NimNode, isRef: bool): NimNode {.compileTime.} =
@ -1558,13 +1566,17 @@ proc processType(typeName: NimNode, obj: NimNode,
## RecList ## RecList
## Sym "events" ## Sym "events"
case obj.kind case obj.kind
of nnkObjectTy: of nnkObjectTy, nnkTupleTy:
# Create object constructor. # Create object constructor.
result = newNimNode(nnkObjConstr) result =
result.add(typeName) # Name of the type to construct. if obj.kind == nnkObjectTy: newNimNode(nnkObjConstr)
else: newNimNode(nnkPar)
# Process each object field and add it as an exprColonExpr if obj.kind == nnkObjectTy:
result.add(processObjFields(obj, jsonNode)) result.add(typeName) # Name of the type to construct.
# 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. # Object might be null. So we need to check for that.
if isRef: if isRef:
@ -1687,6 +1699,8 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
result = createConstructor(obj, jsonNode) result = createConstructor(obj, jsonNode)
else: else:
result = processType(typeSym, obj, jsonNode, false) result = processType(typeSym, obj, jsonNode, false)
of nnkTupleTy:
result = processType(typeSym, typeSym, jsonNode, false)
else: else:
doAssert false, "Unable to create constructor for: " & $typeSym.kind 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 (?) # TODO: Rename postProcessValue and move it (?)
result = postProcessValue(result) result = postProcessValue(result)
# echo(treeRepr(result))
# echo(toStrLit(result)) # echo(toStrLit(result))
when false: when false:

View file

@ -260,3 +260,19 @@ when isMainModule:
let msg = data.to(MsgChallenge) let msg = data.to(MsgChallenge)
doAssert msg.name == "foo" doAssert msg.name == "foo"
doAssert msg.challenge == "bar" 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