diff --git a/modules/module-lua-scripting/pod.c b/modules/module-lua-scripting/pod.c
index 1e3c3ab7591cf0682be7b761859652101543e418..84f8f401fc0ef6570b8118b1c5db5eae28d65462 100644
--- a/modules/module-lua-scripting/pod.c
+++ b/modules/module-lua-scripting/pod.c
@@ -921,6 +921,8 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     guint32 width = 0, height = 0;
     wp_spa_pod_get_rectangle (pod, &width, &height);
     lua_newtable (L);
+    lua_pushstring (L, "Rectangle");
+    lua_setfield (L, -2, "pod_type");
     lua_pushinteger (L, width);
     lua_setfield (L, -2, "width");
     lua_pushinteger (L, height);
@@ -932,6 +934,8 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     guint32 num = 0, denom = 0;
     wp_spa_pod_get_fraction (pod, &num, &denom);
     lua_newtable (L);
+    lua_pushstring (L, "Fraction");
+    lua_setfield (L, -2, "pod_type");
     lua_pushinteger (L, num);
     lua_setfield (L, -2, "num");
     lua_pushinteger (L, denom);
@@ -947,11 +951,14 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     g_autoptr (WpIterator) it = NULL;
     wp_spa_pod_get_object (pod, &id_name, NULL);
     lua_newtable (L);
+    lua_pushstring (L, "Object");
+    lua_setfield (L, -2, "pod_type");
     lua_pushstring (L, wp_spa_type_name (type));
     lua_rawseti (L, -2, 1);
     lua_pushstring (L, id_name);
     lua_rawseti (L, -2, 2);
     it = wp_spa_pod_new_iterator (pod);
+    lua_newtable (L);
     for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
       WpSpaPod *prop = g_value_get_boxed (&item);
       const gchar *key = NULL;
@@ -963,6 +970,7 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
           wp_spa_id_table_find_value_from_short_name (values_table, key));
       lua_setfield (L, -2, key);
     }
+    lua_setfield (L, -2, "properties");
   }
 
   /* Struct */
@@ -971,6 +979,8 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
     guint i = 1;
     lua_newtable (L);
+    lua_pushstring (L, "Struct");
+    lua_setfield (L, -2, "pod_type");
     for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
       WpSpaPod *val = g_value_get_boxed (&item);
       push_luapod (L, val, NULL);
@@ -984,6 +994,8 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
     guint i = 1;
     lua_newtable (L);
+    lua_pushstring (L, "Sequence");
+    lua_setfield (L, -2, "pod_type");
     for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
       WpSpaPod *control = g_value_get_boxed (&item);
       guint32 offset = 0;
@@ -1006,21 +1018,25 @@ push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
     g_autoptr (WpSpaPod) child = wp_spa_pod_get_array_child (pod);
     WpSpaType type = wp_spa_pod_get_spa_type (child);
     lua_newtable (L);
+    lua_pushstring (L, "Array");
+    lua_setfield (L, -2, "pod_type");
     lua_pushstring (L, wp_spa_type_name (type));
-    lua_rawseti (L, -2, 1);
-    push_primitive_values (L, pod, type, 2);
+    lua_setfield (L, -2, "value_type");
+    push_primitive_values (L, pod, type, 1);
   }
 
   /* Choice */
   else if (wp_spa_pod_is_choice (pod)) {
     g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
     WpSpaType type = wp_spa_pod_get_spa_type (child);
-    const gchar *choice_type = NULL;
-    choice_type = wp_spa_id_value_short_name (wp_spa_pod_get_choice_type (pod));
+    g_autofree const gchar *choice_type = g_strdup_printf ("Choice.%s",
+        wp_spa_id_value_short_name (wp_spa_pod_get_choice_type (pod)));
     lua_newtable (L);
     lua_pushstring (L, choice_type);
-    lua_rawseti (L, -2, 1);
-    push_primitive_values (L, pod, type, 2);
+    lua_setfield (L, -2, "pod_type");
+    lua_pushstring (L, wp_spa_type_name (type));
+    lua_setfield (L, -2, "value_type");
+    push_primitive_values (L, pod, type, 1);
   }
 
   /* Error */
diff --git a/tests/wplua/scripts/pod.lua b/tests/wplua/scripts/pod.lua
index f4b9f69207b78542f7b20e29262713f9050cf420..1598708bd865cc84b753c6f30c8ae5bef2617005 100644
--- a/tests/wplua/scripts/pod.lua
+++ b/tests/wplua/scripts/pod.lua
@@ -58,18 +58,21 @@ assert (pod:get_type_name() == "Spa:Fd")
 -- Rectangle
 pod = Pod.Rectangle (1920, 1080)
 val = pod:parse()
+assert (val.pod_type == "Rectangle")
 assert (val.width == 1920 and val.height == 1080)
 assert (pod:get_type_name() == "Spa:Rectangle")
 
 -- Fraction
 pod = Pod.Fraction (3, 4)
 val = pod:parse()
+assert (val.pod_type == "Fraction")
 assert (val.num == 3 and val.denom == 4)
 assert (pod:get_type_name() == "Spa:Fraction")
 
 -- Struct
 pod = Pod.Struct { true, 1, "string" }
 val = pod:parse()
+assert (val.pod_type == "Struct")
 assert (val[1] and val[2] == 1 and val[3] == "string")
 assert (pod:get_type_name() == "Spa:Pod:Struct")
 
@@ -81,11 +84,12 @@ pod = Pod.Object {
   monitor = true
 }
 val = pod:parse()
+assert (val.pod_type == "Object")
 assert (val[1] == "Spa:Pod:Object:Param:PortConfig")
 assert (val[2] == "PortConfig")
-assert (val.direction == "Input")
-assert (val.mode == "dsp")
-assert (val.monitor)
+assert (val.properties.direction == "Input")
+assert (val.properties.mode == "dsp")
+assert (val.properties.monitor)
 assert (pod:get_type_name() == "Spa:Pod:Object:Param:PortConfig")
 
 -- Sequence
@@ -95,6 +99,7 @@ pod = Pod.Sequence {
   {offset = 40, typename = "Properties", value = 4},
 }
 val = pod:parse()
+assert (val.pod_type == "Sequence")
 assert (val[1].offset == 10 and val[1].typename == "Properties" and val[1].value == 1)
 assert (val[2].offset == 20 and val[2].typename == "Properties" and val[2].value == 2)
 assert (val[3].offset == 40 and val[3].typename == "Properties" and val[3].value == 4)
@@ -103,21 +108,23 @@ assert (pod:get_type_name() == "Spa:Pod:Sequence")
 -- Array
 pod = Pod.Array { "Spa:Bool", true, false, false, true }
 val = pod:parse()
-assert (val[1] == "Spa:Bool")
-assert (val[2])
+assert (val.pod_type == "Array")
+assert (val.value_type == "Spa:Bool")
+assert (val[1])
+assert (not val[2])
 assert (not val[3])
-assert (not val[4])
-assert (val[5])
+assert (val[4])
 assert (pod:get_type_name() == "Spa:Array")
 
 -- Choice
 pod = Pod.Choice { "Enum", 5, 6, 7, 8 }
 val = pod:parse()
-assert (val[1] == "Enum")
-assert (val[2] == 5)
-assert (val[3] == 6)
-assert (val[4] == 7)
-assert (val[5] == 8)
+assert (val.pod_type == "Choice.Enum")
+assert (val.value_type == "Spa:Long")
+assert (val[1] == 5)
+assert (val[2] == 6)
+assert (val[3] == 7)
+assert (val[4] == 8)
 assert (pod:get_type_name() == "Spa:Pod:Choice")
 
 -- Nested Pods
@@ -136,14 +143,18 @@ pod = Pod.Object {
   }
 }
 val = pod:parse()
+assert (val.pod_type == "Object")
 assert (val[1] == "Spa:Pod:Object:Param:PortConfig")
 assert (val[2] == "PortConfig")
-assert (val.direction == "Input")
-assert (val.mode == "dsp")
-assert (val.monitor)
-assert (val.format.mediaType == "audio")
-assert (val.format.mediaSubtype == "raw")
-assert (val.format.rate == 48000)
-assert (val.format.channels == 2)
-assert (val.format.position[1] == "Spa:Id" and val.format.position[2] == 0 and val.format.position[3] == 1)
+assert (val.properties.direction == "Input")
+assert (val.properties.mode == "dsp")
+assert (val.properties.monitor)
+assert (val.properties.format.pod_type == "Object")
+assert (val.properties.format.properties.mediaType == "audio")
+assert (val.properties.format.properties.mediaSubtype == "raw")
+assert (val.properties.format.properties.rate == 48000)
+assert (val.properties.format.properties.channels == 2)
+assert (val.properties.format.properties.position.pod_type == "Array")
+assert (val.properties.format.properties.position.value_type == "Spa:Id")
+assert (val.properties.format.properties.position[1] == 0 and val.properties.format.properties.position[2] == 1)
 assert (pod:get_type_name() == "Spa:Pod:Object:Param:PortConfig")