Document to macro in JSON and add example.

This commit is contained in:
Dominik Picheta
2017-04-09 12:48:07 +02:00
parent a883424d0d
commit eedc6fecd7
2 changed files with 71 additions and 22 deletions

View File

@@ -1336,6 +1336,7 @@ proc createGetEnumCall(jsonNode, kindType: NimNode): NimNode =
return getEnumCall
proc createOfBranchCond(ofBranch, getEnumCall: NimNode): NimNode =
## Creates an expression that acts as the condition for an ``of`` branch.
var cond = newIdentNode("false")
for ofCond in ofBranch:
if ofCond.kind == nnkRecList:
@@ -1346,20 +1347,6 @@ proc createOfBranchCond(ofBranch, getEnumCall: NimNode): NimNode =
return cond
proc createIfStmtForOf(ofBranch, jsonNode, kindType,
value: NimNode): NimNode {.compileTime.} =
## Transforms a case ``of`` branch into an if statement to be placed as the
## ExprColonExpr body expr.
expectKind(ofBranch, nnkOfBranch)
let getEnumCall = createGetEnumCall(jsonNode, kindType)
let cond = createOfBranchCond(ofBranch, getEnumCall)
return newIfStmt(
(cond, value)
)
proc createConstructor(typeSym, jsonNode: NimNode): NimNode {.compileTime.}
proc processObjField(field, jsonNode: NimNode): seq[NimNode] {.compileTime.}
proc processOfBranch(ofBranch, jsonNode, kindType,
kindJsonNode: NimNode): seq[NimNode] {.compileTime.} =
@@ -1377,6 +1364,8 @@ proc processOfBranch(ofBranch, jsonNode, kindType,
## Sym "foodPos"
## Sym "enemyPos"
result = @[]
let getEnumCall = createGetEnumCall(kindJsonNode, kindType)
for branchField in ofBranch[^1]:
let objFields = processObjField(branchField, jsonNode)
@@ -1387,8 +1376,10 @@ proc processOfBranch(ofBranch, jsonNode, kindType,
exprColonExpr.add(toIdentNode(objField[0]))
# Add the value of the field.
let ifStmt = createIfStmtForOf(ofBranch, kindJsonNode, kindType, objField[1])
exprColonExpr.add(ifStmt)
let cond = createOfBranchCond(ofBranch, getEnumCall)
exprColonExpr.add(newIfStmt(
(cond, objField[1])
))
proc processElseBranch(recCaseNode, elseBranch, jsonNode, kindType,
kindJsonNode: NimNode): seq[NimNode] {.compileTime.} =
@@ -1427,6 +1418,7 @@ proc processElseBranch(recCaseNode, elseBranch, jsonNode, kindType,
let ifStmt = newIfStmt((cond, objField[1]))
exprColonExpr.add(ifStmt)
proc createConstructor(typeSym, jsonNode: NimNode): NimNode {.compileTime.}
proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
## Process a field from a ``RecList``.
##
@@ -1541,8 +1533,8 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
## The ``jsonNode`` refers to the node variable that we are deserialising.
##
## Returns an object constructor node.
echo("--createConsuctor-- \n", treeRepr(typeSym))
echo()
# echo("--createConsuctor-- \n", treeRepr(typeSym))
# echo()
case typeSym.kind
of nnkBracketExpr:
@@ -1576,7 +1568,6 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
else:
# Generic type.
let obj = getType(typeSym)
echo(obj.treeRepr, typeSym[0].treeRepr)
result = processType(typeSym, obj, jsonNode)
of nnkSym:
let obj = getType(typeSym)
@@ -1667,6 +1658,40 @@ proc postProcess(node: NimNode): NimNode =
macro to*(node: JsonNode, T: typedesc): untyped =
## `Unmarshals`:idx: the specified node into the object type specified.
##
## Known limitations:
##
## * Heterogeneous arrays are not supported.
## * Sets in object variants are not supported.
##
## Example:
##
## .. code-block:: Nim
## let jsonNode = parseJson("""
## {
## "person": {
## "name": "Nimmer",
## "age": 21
## },
## "list": [1, 2, 3, 4]
## }
## """)
##
## type
## Person = object
## name: string
## age: int
##
## Data = object
## person: Person
## list: seq[int]
##
## var data = to(jsonNode, Data)
## doAssert data.person.name == "Nimmer"
## doAssert data.person.age == 21
## doAssert data.list == @[1, 2, 3, 4]
let typeNode = getType(T)
expectKind(typeNode, nnkBracketExpr)
assert(($typeNode[0]).normalize == "typedesc")
@@ -1674,9 +1699,7 @@ macro to*(node: JsonNode, T: typedesc): untyped =
result = createConstructor(typeNode[1], node)
result = postProcess(result)
echo(toStrLit(result))
# TODO: Remove this
#result = newStmtList()
#echo(toStrLit(result))
when false:
import os

View File

@@ -91,6 +91,7 @@ when isMainModule:
doAssert result.other == node["other"].getNum()
# TODO: Test object variant with set in of branch.
# TODO: Should we support heterogenous arrays?
# Tests that verify the error messages for invalid data.
block:
@@ -141,3 +142,28 @@ when isMainModule:
except:
doAssert false
# Test the example in json module.
block:
let jsonNode = parseJson("""
{
"person": {
"name": "Nimmer",
"age": 21
},
"list": [1, 2, 3, 4]
}
""")
type
Person = object
name: string
age: int
Data = object
person: Person
list: seq[int]
var data = to(jsonNode, Data)
doAssert data.person.name == "Nimmer"
doAssert data.person.age == 21
doAssert data.list == @[1, 2, 3, 4]