diff options
-rw-r--r-- | lib/pure/json.nim | 17 | ||||
-rw-r--r-- | tests/stdlib/tjsonmacro.nim | 36 |
2 files changed, 49 insertions, 4 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 1ef08f547..23b23b4a4 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1369,11 +1369,20 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = for `forLoopI` in 0 ..< `jsonNode`.len: list[`forLoopI`] =`constructorNode`; list ) - + of "tuple": + let typeNode = getTypeImpl(typeSym) + result = createConstructor(typeNode, jsonNode) else: - # Generic type. + # Generic type or some `seq[T]` alias let obj = getType(typeSym) - result = processType(typeSym, obj, jsonNode, false) + case obj.kind + of nnkBracketExpr: + # probably a `seq[T]` alias + let typeNode = getTypeImpl(typeSym) + result = createConstructor(typeNode, jsonNode) + else: + # generic type + result = processType(typeSym, obj, jsonNode, false) of nnkSym: # Handle JsonNode. if ($typeSym).cmpIgnoreStyle("jsonnode") == 0: @@ -1385,7 +1394,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = if typeNode.typeKind == ntyDistinct: result = createConstructor(typeNode, jsonNode) elif obj.kind == nnkBracketExpr: - # When `Sym "Foo"` turns out to be a `ref object`. + # When `Sym "Foo"` turns out to be a `ref object` or `tuple` result = createConstructor(obj, jsonNode) else: result = processType(typeSym, obj, jsonNode, false) diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 0521d558c..85530065d 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -517,6 +517,42 @@ when true: doAssert v.name == "smith" doAssert MyRef(w).name == "smith" +# bug #12015 +# The definition of the `%` proc needs to be here, since the `% c` calls below +# can only find our custom `%` proc for `Pix` if defined in global scope. +type + Pix = tuple[x, y: uint8, ch: uint16] +proc `%`(p: Pix): JsonNode = + result = %* { "x" : % p.x, + "y" : % p.y, + "ch" : % p.ch } +block: + type + Cluster = object + works: tuple[x, y: uint8, ch: uint16] # working + fails: Pix # previously broken + + let data = (x: 123'u8, y: 53'u8, ch: 1231'u16) + let c = Cluster(works: data, fails: data) + let cFromJson = (% c).to(Cluster) + doAssert c == cFromJson + +block: + # bug related to #12015 + type + PixInt = tuple[x, y, ch: int] + SomePix = Pix | PixInt + Cluster[T: SomePix] = seq[T] + ClusterObject[T: SomePix] = object + data: Cluster[T] + RecoEvent[T: SomePix] = object + cluster: seq[ClusterObject[T]] + + let data = @[(x: 123'u8, y: 53'u8, ch: 1231'u16)] + var c = RecoEvent[Pix](cluster: @[ClusterObject[Pix](data: data)]) + let cFromJson = (% c).to(RecoEvent[Pix]) + doAssert c == cFromJson + # TODO: when the issue with the limeted vm registers is solved, the # exact same test as above should be evaluated at compile time as # well, to ensure that the vm functionality won't diverge from the |