util.datamapper: Fix arrays nesting one level too deep
authorKim Alvefur <zash@zash.se>
Fri, 19 Mar 2021 01:17:59 +0100
changeset 11466 d1982b7eb00d
parent 11465 766b0eddd12c
child 11467 21523e3d395e
util.datamapper: Fix arrays nesting one level too deep
spec/util_datamapper_spec.lua
teal-src/util/datamapper.tl
util/datamapper.lua
--- a/spec/util_datamapper_spec.lua	Fri Mar 19 00:26:04 2021 +0100
+++ b/spec/util_datamapper_spec.lua	Fri Mar 19 01:17:59 2021 +0100
@@ -46,10 +46,13 @@
 					type = "string";
 					xml = {name = "origin-id"; namespace = "urn:xmpp:sid:0"; x_single_attribute = "id"};
 				};
-				reactions = {
-					type = "array";
-					xml = {namespace = "urn:xmpp:reactions:0"; wrapped = true};
-					items = {type = "string"; xml = {name = "reaction"}};
+				react = {
+					type = "object";
+					xml = {namespace = "urn:xmpp:reactions:0"; name = "reactions"};
+					properties = {
+						to = {type = "string"; xml = {attribute = true; name = "id"}};
+						reactions = {type = "array"; items = {type = "string"; xml = {name = "reaction"}}};
+					};
 				};
 			};
 		};
@@ -80,9 +83,12 @@
 			state = "active";
 			fallback = true;
 			origin_id = "qgkmMdPB";
-			reactions = {
-				"👋",
-				"🐢",
+			react = {
+				to = "744f6e18-a57a-11e9-a656-4889e7820c76";
+				reactions = {
+					"👋",
+					"🐢",
+				};
 			};
 		};
 	end);
@@ -102,6 +108,8 @@
 			assert.equal(x:get_child_text("delay", "urn:xmpp:delay"), u:get_child_text("delay", "urn:xmpp:delay"));
 			assert.same(x:get_child("delay", "urn:xmpp:delay").attr, u:get_child("delay", "urn:xmpp:delay").attr);
 			assert.same(x:get_child("origin-id", "urn:xmpp:sid:0").attr, u:get_child("origin-id", "urn:xmpp:sid:0").attr);
+			assert.same(x:get_child("reactions", "urn:xmpp:reactions:0").attr, u:get_child("reactions", "urn:xmpp:reactions:0").attr);
+			assert.same(2, #u:get_child("reactions", "urn:xmpp:reactions:0").tags);
 			for _, tag in ipairs(x.tags) do
 				if tag.name ~= "UNRELATED" then
 					assert.truthy(u:get_child(tag.name, tag.attr.xmlns) or u:get_child(tag.name), tag:top_tag())
--- a/teal-src/util/datamapper.tl	Fri Mar 19 00:26:04 2021 +0100
+++ b/teal-src/util/datamapper.tl	Fri Mar 19 01:17:59 2021 +0100
@@ -216,7 +216,7 @@
 	end
 end
 
-local function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string ) : st.stanza_t
+local function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string, ctx : st.stanza_t ) : st.stanza_t
 
 	if schema.xml then
 		if schema.xml.name then
@@ -228,7 +228,7 @@
 		-- TODO prefix?
 	end
 
-	local out = st.stanza(current_name, { xmlns = current_ns })
+	local out = ctx or st.stanza(current_name, { xmlns = current_ns })
 
 	if schema.type == "object" then
 
@@ -303,15 +303,13 @@
 							out:add_direct_child(c);
 						end
 					elseif proptype == "array" and propschema is json_schema_object and v is table then
-						local c = unparse(propschema, v, name, namespace);
-						if c then
-							if value_where == "in_wrapper" then
-								local w = st.stanza(propschema.xml.name or name, { xmlns = propschema.xml.namespace or namespace })
-								w:add_direct_child(c);
-								out:add_direct_child(w);
-							else
+						if value_where == "in_wrapper" then
+							local c = unparse(propschema, v, name, namespace);
+							if c then
 								out:add_direct_child(c);
 							end
+						else
+							unparse(propschema, v, name, namespace, out);
 						end
 					else
 						error "NYI"
--- a/util/datamapper.lua	Fri Mar 19 00:26:04 2021 +0100
+++ b/util/datamapper.lua	Fri Mar 19 01:17:59 2021 +0100
@@ -1,5 +1,7 @@
 local st = require("util.stanza");
 
+local schema_t = {}
+
 local function toboolean(s)
 	if s == "true" or s == "1" then
 		return true
@@ -181,7 +183,7 @@
 	end
 end
 
-local function unparse(schema, t, current_name, current_ns)
+local function unparse(schema, t, current_name, current_ns, ctx)
 
 	if schema.xml then
 		if schema.xml.name then
@@ -193,7 +195,7 @@
 
 	end
 
-	local out = st.stanza(current_name, {xmlns = current_ns})
+	local out = ctx or st.stanza(current_name, {xmlns = current_ns})
 
 	if schema.type == "object" then
 
@@ -268,15 +270,13 @@
 							out:add_direct_child(c);
 						end
 					elseif proptype == "array" and type(propschema) == "table" and type(v) == "table" then
-						local c = unparse(propschema, v, name, namespace);
-						if c then
-							if value_where == "in_wrapper" then
-								local w = st.stanza(propschema.xml.name or name, {xmlns = propschema.xml.namespace or namespace})
-								w:add_direct_child(c);
-								out:add_direct_child(w);
-							else
+						if value_where == "in_wrapper" then
+							local c = unparse(propschema, v, name, namespace);
+							if c then
 								out:add_direct_child(c);
 							end
+						else
+							unparse(propschema, v, name, namespace, out);
 						end
 					else
 						error("NYI")