From e58cb1bb74628f46fef0db914477beeb44230cd4 Mon Sep 17 00:00:00 2001 From: HeWhoWalksBehind <84110044+siriuslee69@users.noreply.github.com> Date: Sun, 8 Sep 2024 03:34:31 +0200 Subject: [PATCH 1/5] Update json.nim `%` - Conversion of an object or tuple to JsonNode doesn't work correctly for tuples atm, since the generic type is missing. Added the tuple generic type to correctly allow tuples as input as well. Credits to Elegantbeef from the Nim Discord. --- lib/pure/json.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 3d68ae5cf655..2e8bace9fe66 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -390,7 +390,7 @@ proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) {.inline.} = assert(obj.kind == JObject) obj.fields[key] = val -proc `%`*[T: object](o: T): JsonNode = +proc `%`*[T: object | tuple](o: T): JsonNode = ## Construct JsonNode from tuples and objects. result = newJObject() for k, v in o.fieldPairs: result[k] = %v From 6752e7d289386f995d23f88c8ccd3431beb22d39 Mon Sep 17 00:00:00 2001 From: HeWhoWalksBehind <84110044+siriuslee69@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:17:49 +0200 Subject: [PATCH 2/5] Update tjson.nim - added test for tuple to JSON obj conversion Deleted old test: not compiles(%{"error": "No messages"}) Added new test to check whether tuple to JsonNode conversion via `%` works correctly now. (Both for named tuple and anonymous tuple.) Interesting background info I stumbled upon: At some point in the past, anonymous tuples and named tuples were converted to different JSON types. Anonymous tuples were converted to JSON arrays (because their fields didn't have names) and named tuples to JSON objects (because their fields had names). At some point this was (correctly) changed, and both now convert to JSON objects. For anonymous tuples the respective JSON object field-names are constructed by naming them as such: "Field0" for field 0, "Field1" for field 1, "Field2" for field 2, etc. ... --- tests/stdlib/tjson.nim | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index 691bedeaabe7..7c2a88677494 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -173,7 +173,19 @@ when not defined(js): doAssert($ %*[] == "[]") doAssert($ %*{} == "{}") -doAssert(not compiles(%{"error": "No messages"})) +#issue #24082 for more info +block test_tuple: + let + test_tuple_named: tuple = (a1: 10, a2: "foo") #tuple with field names = named tuple + test_tuple_anon: tuple = (10, "foo") #tuple without field names = anonymous tuple + + doAssert $(% test_tuple_named) == """{"a1":10,"a2":"foo"}""" + doAssert $(% test_tuple_anon) == """{"Field0":10,"Field1":"foo"]""" + + doAssert $(%* test_tuple_named) == """{"a1":10,"a2":"foo"}""" + doAssert $(%* test_tuple_anon) == """{"Field0":10,"Field1":"foo"]""" + + # bug #9111 block: From cdd2950dcc1e85da87d2fac18bcb7f72d025250b Mon Sep 17 00:00:00 2001 From: HeWhoWalksBehind <84110044+siriuslee69@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:25:29 +0200 Subject: [PATCH 3/5] Update tjson.nim - left in wrong bracket forgot to remove a bracket "]" and replaced it with "}" whoops --- tests/stdlib/tjson.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index 7c2a88677494..dc4a6130cffd 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -180,10 +180,10 @@ block test_tuple: test_tuple_anon: tuple = (10, "foo") #tuple without field names = anonymous tuple doAssert $(% test_tuple_named) == """{"a1":10,"a2":"foo"}""" - doAssert $(% test_tuple_anon) == """{"Field0":10,"Field1":"foo"]""" + doAssert $(% test_tuple_anon) == """{"Field0":10,"Field1":"foo"}""" doAssert $(%* test_tuple_named) == """{"a1":10,"a2":"foo"}""" - doAssert $(%* test_tuple_anon) == """{"Field0":10,"Field1":"foo"]""" + doAssert $(%* test_tuple_anon) == """{"Field0":10,"Field1":"foo"}""" From c363d93f9bc698b3504e164781a4dcf44658be59 Mon Sep 17 00:00:00 2001 From: HeWhoWalksBehind <84110044+siriuslee69@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:44:55 +0200 Subject: [PATCH 4/5] Update tjson.nim Update tjson.nim - applied camelCase to the test vars to fit the conventions --- tests/stdlib/tjson.nim | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index dc4a6130cffd..590cd72cd8c8 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -174,16 +174,16 @@ doAssert($ %*[] == "[]") doAssert($ %*{} == "{}") #issue #24082 for more info -block test_tuple: +block testTuple: let - test_tuple_named: tuple = (a1: 10, a2: "foo") #tuple with field names = named tuple - test_tuple_anon: tuple = (10, "foo") #tuple without field names = anonymous tuple + testTupleNamed: tuple = (a1: 10, a2: "foo") #tuple with field names = named tuple + testTupleAnon: tuple = (10, "foo") #tuple without field names = anonymous tuple - doAssert $(% test_tuple_named) == """{"a1":10,"a2":"foo"}""" - doAssert $(% test_tuple_anon) == """{"Field0":10,"Field1":"foo"}""" + doAssert $(% testTupleNamed) == """{"a1":10,"a2":"foo"}""" + doAssert $(% testTupleAnon) == """{"Field0":10,"Field1":"foo"}""" - doAssert $(%* test_tuple_named) == """{"a1":10,"a2":"foo"}""" - doAssert $(%* test_tuple_anon) == """{"Field0":10,"Field1":"foo"}""" + doAssert $(%* testTupleNamed) == """{"a1":10,"a2":"foo"}""" + doAssert $(%* testTupleAnon) == """{"Field0":10,"Field1":"foo"}""" From 8de1e9b6c8fbaff8748c8888fc294083d8e891b4 Mon Sep 17 00:00:00 2001 From: HeWhoWalksBehind <84110044+siriuslee69@users.noreply.github.com> Date: Mon, 9 Sep 2024 02:23:41 +0200 Subject: [PATCH 5/5] disallow passing arrays of tuples as arguments to `%` Nim converts {"key":"val"} to [("key", "val")] at compile time. So {} is a tuple inside an array actually. Using the % operator on this will pass it as an argument to the respective function that takes an openarray as argument and convert the tuple inside this array: %{"key":"val"} becomes [{"Field0":"key","Field1":"val"}]. As to why this is a problem, I do not know, but two tests failed because of that. Before, this wasn't a problem, because one of the `%` procedures that was supposed to accept tuples and convert them to JsonNodes only accepted objects. Now that we also want to convert tuples to a JSON object as well via `%`, we have to make sure that {} is not handled as a tuple inside an array also. --- lib/pure/json.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 2e8bace9fe66..e5f1e55e0464 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -357,7 +357,9 @@ proc `%`*(keyVals: openArray[tuple[key: string, val: JsonNode]]): JsonNode = template `%`*(j: JsonNode): JsonNode = j -proc `%`*[T](elements: openArray[T]): JsonNode = +#Disallow tuples inside the array to avoid something like %{"test":"test1"} to get converted to [{"Field0":"test","Field1":"test1"}]. +#See issue #24082 +proc `%`*[T: not tuple](elements: openArray[T]): JsonNode = ## Generic constructor for JSON data. Creates a new `JArray JsonNode` result = newJArray() for elem in elements: result.add(%elem)