From 81325d07452f61a578853b926eb84f3b56ef8676 Mon Sep 17 00:00:00 2001 From: Jake Leahy Date: Wed, 19 Aug 2026 16:24:25 +1000 Subject: [PATCH] Add checks to `fromJson` when trying to convert to an array (#26109) Issue popped up when using `fromJson` into an array but the JSON passed is an object ```nim import std/[jsonutils, json] let data = parseJson """ {"key": "value"} """ var foo: seq[int] foo.fromJson(data) echo foo #> @[0] ``` Basically the `setLen` would set the size to be equal to the number of keys, but `getElems` just returns an empty array if the JSON isn't an array which lead to it just creating zero'd items in the seq without letting the user know. Felt adding the checks was better than just skipping the `setLen` since it lets the user know that there is a problem with the JSON --- changelog.md | 1 + lib/std/jsonutils.nim | 2 ++ tests/stdlib/tjsonutils.nim | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/changelog.md b/changelog.md index 024d607dee..d6561b42d2 100644 --- a/changelog.md +++ b/changelog.md @@ -99,6 +99,7 @@ parameter and result types, not just their source-level shape. Use works without single-quoting. - `std/uri`: The `?` operator now appends query parameters to an existing query string instead of replacing it. Fixes [#19782](https://github.com/nim-lang/Nim/issues/19782). +- `std/jsonutils`: `fromJson` now throws an exception when converting to `array`/`seq` if the JSON isn't an array instead of silently failing ## Language changes diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim index d378812b69..688bbdb565 100644 --- a/lib/std/jsonutils.nim +++ b/lib/std/jsonutils.nim @@ -238,6 +238,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) = a = T() fromJson(a[], b, opt) elif T is array: + checkJson b.kind == JArray checkJson a.len == b.len, "Json array size doesn't match for " & $T var i = 0 for ai in mitems(a): @@ -248,6 +249,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) = for val in b.getElems: incl a, jsonTo(val, E) elif T is seq: + checkJson b.kind == JArray a.setLen b.len for i, val in b.getElems: fromJson(a[i], val, opt) diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim index b57cb3e914..3411faa8b6 100644 --- a/tests/stdlib/tjsonutils.nim +++ b/tests/stdlib/tjsonutils.nim @@ -451,6 +451,12 @@ template fn() = let json = inner.toJson(ToJsonOptions(enumMode: joptEnumSymbol)) doAssert $json == """{"x":"hello","y":"A"}""" + block arrayTypeCheck: + let json = """{"key": "value"}""".parseJson() + var output: seq[int] + doAssertRaises(ValueError): + output.fromJson(json) + block: # bug #21638 type Something = object