summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/std/jsonutils.nim14
-rw-r--r--tests/stdlib/tjsonutils.nim8
2 files changed, 19 insertions, 3 deletions
diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim
index 9db1106c4..05f9f661c 100644
--- a/lib/std/jsonutils.nim
+++ b/lib/std/jsonutils.nim
@@ -32,7 +32,7 @@ add a way to customize serialization, for e.g.:
 
 import macros
 from enumutils import symbolName
-from typetraits import OrdinalEnum
+from typetraits import OrdinalEnum, tupleLen
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -286,11 +286,21 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
       fromJsonFields(a, nil, b, seq[string].default, opt)
     else:
       checkJson b.kind == JArray, $(b.kind) # we could customize whether to allow JNull
+
+      when compiles(tupleLen(T)):
+        let tupleSize = tupleLen(T)
+      else:
+        # Tuple len isn't in csources_v1 so using tupleLen would fail.
+        # Else branch basically never runs (tupleLen added in 1.1 and jsonutils in 1.4), but here for consistency
+        var tupleSize = 0
+        for val in fields(a):
+          tupleSize.inc
+
+      checkJson b.len == tupleSize, $(b.len, tupleSize, $T, b) # could customize
       var i = 0
       for val in fields(a):
         fromJson(val, b[i], opt)
         i.inc
-      checkJson b.len == i, $(b.len, i, $T, b) # could customize
   else:
     # checkJson not appropriate here
     static: doAssert false, "not yet implemented: " & $T
diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim
index 12a4b20eb..1681f4a09 100644
--- a/tests/stdlib/tjsonutils.nim
+++ b/tests/stdlib/tjsonutils.nim
@@ -410,6 +410,13 @@ template fn() =
       doAssert foo.c == 0
       doAssert foo.c0 == 42
 
+
+    block testInvalidTupleLength:
+      let json = parseJson("[0]")
+      # Should raise ValueError instead of index error
+      doAssertRaises(ValueError):
+        discard json.jsonTo((int, int))
+
     type
       InnerEnum = enum
         A
@@ -431,7 +438,6 @@ template fn() =
       let json = inner.toJson(ToJsonOptions(enumMode: joptEnumSymbol))
       doAssert $json == """{"x":"hello","y":"A"}"""
 
-
     when false:
       ## TODO: Implement support for nested variant objects allowing the tests
       ## bellow to pass.