I am trying to use macro for automatic initializer proc generation, here is the code func typeMap(k: JsonNodeKind): string = case k: of JBool: "bool" of JInt: "int" of JFloat: "float" of JString: "string" else: error("Unsupported json kind: " & $k) func nodeMap(j: JsonNode): NimNode = case j.kind of JNull: result = newNilLit() of JBool: result = newLit(j.getBool()) of JInt: result = newLit(j.getInt()) of JFloat: result = newLit(j.getFloat()) of JString: result = newLit(j.getStr()) else: error("Unsupported json kind: " & $j) macro TABLE_FROM_JSON*(json: static string, name: untyped): untyped = result = newStmtList() let fields = parseJson(json).getFields().pairs.toSeq() let fieldsAst = nnkRecList.newTree( fields.mapIt( nnkIdentDefs.newTree( newTree(nnkPostfix, newIdentNode("*"), newIdentNode($it[0])), ident typeMap(it[1].kind), newEmptyNode() ) ) ) # Generate the base type let baseType = newTree(nnkTypeSection, newTree(nnkTypeDef, newTree(nnkPostfix, newIdentNode("*"), newTree(nnkAccQuoted, name) ), newEmptyNode(), newTree(nnkObjectTy, newEmptyNode(), newEmptyNode(), # # Replace the specific AST with a generic one : fieldsAst ) ) ) result.add(baseType) # Generate the table type let tableType = newTree(nnkTypeSection, newTree(nnkTypeDef, newTree(nnkPostfix, newIdentNode("*"), newTree(nnkAccQuoted, name, newIdentNode("Table") ) ), newEmptyNode(), newTree(nnkObjectTy, newEmptyNode(), newEmptyNode(), newTree(nnkRecList, newTree(nnkIdentDefs, newTree(nnkPostfix, newIdentNode("*"), newIdentNode("list")), newTree(nnkBracketExpr, newIdentNode("seq"), newTree(nnkAccQuoted, name) ), newEmptyNode() ) ) ) ) ) result.add(tableType) let InitStmt = newStmtList( newCall( newDotExpr( newDotExpr(newIdentNode("result"), newIdentNode("list")), newIdentNode("add") ), newTree(nnkObjConstr, newIdentNode(strVal(name)), # This way make Error: incorrect object construction syntax # nnkArgList.newColonExpr( # fields.mapIt( # newIdentNode($it[0]), nodeMap(it[1]) # ) # ) # working Example newColonExpr(newIdentNode("name"), newLit("Alice")), newColonExpr(newIdentNode("age"), newLit(30)), newColonExpr(newIdentNode("address"), newLit("23 Main St")) ) ) ) let tableInit = newProc( name = newTree(nnkPostfix, newIdentNode("*"), newTree(nnkAccQuoted, newIdentNode("new") , name , newIdentNode("Table"))), # name = newIdentNode("newPersonTable"), # params = [newIdentNode("PersonTable")], params = [newTree(nnkAccQuoted, name , newIdentNode("Table"))], body = InitStmt ) result.add(tableInit) Run
here is test code const exampleDataStr = """{"name": "JK", "age": 30, "address": "Tokyo"}""" TABLE_FROM_JSON(exampleDataStr, Person) var pt = newPersonTable() for p in pt.list: echo p.name, " is ", p.age, " years old and lives at ", p.address Run