From 8187e83645bbc9d536eebfab2af3b2437c3485fb Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 29 Nov 2017 20:30:40 +0000 Subject: [PATCH] Implement Table/OrderedTable support for json.to macro. --- lib/pure/json.nim | 24 ++++++++++++++++++++++++ tests/stdlib/tjsonmacro.nim | 27 +++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index b057aa7c6e..6153e2f03a 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1677,6 +1677,30 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = ( if `lenientJsonNode`.isNil: `workaround`[`optionGeneric`]() else: some[`optionGeneric`](`value`) ) + of "table", "orderedtable": + let tableKeyType = typeSym[1] + if ($tableKeyType).cmpIgnoreStyle("string") != 0: + error("JSON doesn't support keys of type " & $tableKeyType) + let tableValueType = typeSym[2] + + let forLoopKey = genSym(nskForVar, "key") + let indexerNode = createJsonIndexer(jsonNode, forLoopKey) + let constructorNode = createConstructor(tableValueType, indexerNode) + + let tableInit = + if bracketName == "table": + bindSym("initTable") + else: + bindSym("initOrderedTable") + + # Create a statement expression containing a for loop. + result = quote do: + ( + var map = `tableInit`[`tableKeyType`, `tableValueType`](); + verifyJsonKind(`jsonNode`, {JObject}, astToStr(`jsonNode`)); + for `forLoopKey` in keys(`jsonNode`.fields): map[`forLoopKey`] = `constructorNode`; + map + ) of "ref": # Ref type. var typeName = $typeSym[1] diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index f9f94606cc..01fa43aa7e 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -2,7 +2,7 @@ discard """ file: "tjsonmacro.nim" output: "" """ -import json, strutils, options +import json, strutils, options, tables when isMainModule: # Tests inspired by own use case (with some additional tests). @@ -315,5 +315,28 @@ when isMainModule: doAssert noYearDeser.year.isNone doAssert noYearDeser.engine.name == "V8" - # TODO: Table[T, Y] support. + # Table[T, Y] support. + block: + type + Friend = object + name: string + age: int + + Dynamic = object + name: string + friends: Table[string, Friend] + + let data = """ + {"friends": { + "John": {"name": "John", "age": 35}, + "Elizabeth": {"name": "Elizabeth", "age": 23} + }, "name": "Dominik"} + """ + + let dataParsed = parseJson(data) + let dataDeser = to(dataParsed, Dynamic) + doAssert dataDeser.name == "Dominik" + doAssert dataDeser.friends["John"].age == 35 + doAssert dataDeser.friends["Elizabeth"].age == 23 + # TODO: JsonNode support \ No newline at end of file