Answering my own question in case anyone else can benefit from the information. The code that I ended up with in order to encode the described structure is the following: void add_elem(GVariantBuilder *builder, struct tree_entry *elem) { GVariantBuilder *new, *child_builder, *children; GVariant *new_dict, *new_array, *search; GList *item; /* This is the new dictionary that will be inserted into the * 'children' array of the parent. The parent could be a regular * element of the master list since both are using an array of * dictionaries for the "children". */ new = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); /* This is the dictionary that will contain the child information. * It only has one key - the id of the current element. */ child_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); /* Construct and add the 'search' type information tuple to the * current element's dictionary. */ search = g_variant_new("(us)", elem->search.type, elem->search.term); g_variant_builder_add(child_builder, "{sv}", "search", search); /* Construct the 'children' array for the child element. This is * effectively the same as what we are doing for the master array. */ children = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}")); for (item = elem->children; item; item = item->next) add_elem(children, item->data); new_array = g_variant_builder_end(children); g_variant_builder_unref(children); /* Add the 'children' array to the current element dictionary. */ g_variant_builder_add(child_builder, "{sv}", "children", new_array); new_dict = g_variant_builder_end(child_builder); g_variant_builder_unref(child_builder); /* Insert the new child into the top level dictionary describing the * current element. */ g_variant_builder_add(new, "{sv}", elem->id, new_dict); /* Insert this element into the parent's 'children' array. */ g_variant_builder_add(builder, "a{sv}", new); } builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}")); add_elem(builder, &root); dict = g_variant_builder_end(builder); On Tue, Feb 26, 2019 at 7:49 AM Mitko Haralanov <voidtrance@xxxxxxxxx> wrote: > > Does anyone have any pointers? > > Thank you. > > On Fri, Feb 22, 2019 at 11:58 AM Mitko Haralanov <voidtrance@xxxxxxxxx> wrote: > > > > Hi, > > > > I've been trying to figure out how to use GVariantBuilder to build a > > complex structure with little success. The type of structure that I > > would like to build is meant to partially encode a GtkTreeModel > > structure. So, I thought that I could use GVariantBuilder to build a > > structure of nested dictionaries. > > > > The structure roughly follows this model: > > [ > > { > > "id": { "key1": (<int>, <string>, ...), "children": [ > > { "id2" : { "key1" : (<int>, <string>, ...), > > "children" : []}, > > { "id3" : { "key1" : (<int>, <string>, ...), > > "children" : [ > > { ... } > > ]} > > ]}}, > > { "id" : ...} > > ] > > > > This type of encoding can naturally be done with recursion and using > > multiple GVariantBuilder's to add to the correct parent. However, I am > > having difficulty with getting the formatting strings correct. As it > > turns out, GLib insist on every dictionary entry being statically > > typed meaning that the values for both "key1" and "children" has to be > > of the same type. That seems to leave only 'v' as a valid format. So, > > I have the following code (only important parts are pasted, not a > > complete program): > > > > struct tree_entry_search { > > uint32_t type; > > const char *term; > > }; > > > > struct tree_entry { > > const char *id; > > struct tree_entry_search search; > > GList *children; > > }; > > > > void add_elem(GVariantBuilder *builder, struct tree_entry *elem) > > { > > GVariantBuilder *new, *child_builder; > > GVariant *new_dict, *new_array, *search; > > GList *item; > > > > new = g_variant_builder_new(G_VARIANT_TYPE_DICTIONARY); > > search = g_variant_new("(us)", elem->search.type, elem->search.term); > > g_variant_builder_add(new, "{sv}", "search", search); > > child_builder = g_variant_builder_new(G_VARIANT_TYPE("av")); > > for (item = elem->children; item; item = item->next) > > add_elem(child_builder, item->data); > > new_array = g_variant_builder_end(child_builder); > > g_variant_builder_unref(child_builder); > > g_variant_builder_add(new, "{sv}", "children", new_array); > > new_dict = g_variant_builder_end(new); > > g_variant_builder_unref(new); > > g_variant_builder_add(builder, "{sv}", elem->id, new_dict); > > } > > > > int main(void) { > > ... > > /* Build up a fake tree. */ > > root.id = g_strdup("uid1"); > > root.search.type = 1; > > root.search.term = g_strdup("term1"); > > elem = g_new0(struct tree_entry, 1); > > elem->id = g_strdup("uid2"); > > elem->search.type = 2; > > elem->search.term = g_strdup("term2"); > > root.children = g_list_append(root.children, elem); > > elem = g_new0(struct tree_entry, 1); > > elem->id = g_strdup("uid3"); > > elem->search.type = 2; > > elem->search.term = g_strdup("term3"); > > root.children = g_list_append(root.children, elem); > > child = g_new0(struct tree_entry, 1); > > child->id = g_strdup("uid4"); > > child->search.type = 3; > > child->search.term = g_strdup("term4"); > > elem->children = g_list_append(elem->children, child); > > > > builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); > > add_elem(builder, &root); > > dict = g_variant_builder_end(builder); > > dictionary = g_variant_print(dict, TRUE); > > printf("%s\n", dictionary); > > ... > > } > > > > But when I compile the above and run it, I get the following errors > > when the tree is more than one level deep: > > > > (process:3873): GLib-CRITICAL **: 11:44:03.826: > > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type > > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed > > > > (process:3873): GLib-CRITICAL **: 11:44:03.827: > > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type > > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed > > > > (process:3873): GLib-CRITICAL **: 11:44:03.827: > > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type > > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed > > > > What's the correct way to specify the builder and variant types so I > > can build the nested dictionary structure? > > > > Thank you for the help. _______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx https://mail.gnome.org/mailman/listinfo/gtk-list