1 /* json-gvariant.c - JSON GVariant integration
3 * This file is part of JSON-GLib
4 * Copyright (C) 2007 OpenedHand Ltd.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
17 * Eduardo Lima Mitev <elima@igalia.com>
28 #include <glib/gi18n-lib.h>
30 #include "json-gvariant.h"
33 * SECTION:json-gvariant
34 * @short_description: Serialize and deserialize GVariant types
35 * @Title: JSON GVariant Integration
37 * Use json_gvariant_serialize() and json_gvariant_serialize_data() to
38 * convert from any #GVariant value to a #JsonNode tree or its string
41 * Use json_gvariant_deserialize() and json_gvariant_deserialize_data() to
42 * obtain the #GVariant value from a #JsonNode tree or directly from a JSON
44 * Since many #GVariant data types cannot be directly represented as
45 * JSON, a #GVariant type string (signature) should be provided to these
46 * methods in order to obtain a correct, type-contrained result.
47 * If no signature is provided, conversion can still be done, but the
48 * resulting #GVariant value will be "guessed" from the JSON data types,
49 * according to the following table:
51 * <table frame='all'><title>Default JSON to GVariant conversion (without signature constrains)</title>
52 * <tgroup cols='2' align='left' colsep='1' rowsep='1'>
56 * <entry>GVariant</entry>
61 * <entry>string</entry>
62 * <entry>string (s)</entry>
65 * <entry>int64</entry>
66 * <entry>int64 (x)</entry>
69 * <entry>boolean</entry>
70 * <entry>boolean (b)</entry>
73 * <entry>double</entry>
74 * <entry>double (d)</entry>
77 * <entry>array</entry>
78 * <entry>array of variants (av)</entry>
81 * <entry>object</entry>
82 * <entry>dictionary of string-variant (a{sv})</entry>
86 * <entry>maybe variant (mv)</entry>
93 /* custom extension to the GVariantClass enumeration to differentiate
94 * a single dictionary entry from an array of dictionary entries
96 #define JSON_G_VARIANT_CLASS_DICTIONARY 'c'
98 typedef void (* GVariantForeachFunc) (GVariant *variant_child,
101 static GVariant * json_to_gvariant_recurse (JsonNode *json_node,
102 const gchar **signature,
105 /* ========================================================================== */
106 /* GVariant to JSON */
107 /* ========================================================================== */
110 gvariant_foreach (GVariant *variant,
111 GVariantForeachFunc func,
115 GVariant *variant_child;
117 g_variant_iter_init (&iter, variant);
118 while ((variant_child = g_variant_iter_next_value (&iter)) != NULL)
120 func (variant_child, user_data);
121 g_variant_unref (variant_child);
126 gvariant_to_json_array_foreach (GVariant *variant_child,
129 JsonArray *array = user_data;
130 JsonNode *json_child;
132 json_child = json_gvariant_serialize (variant_child);
133 json_array_add_element (array, json_child);
137 gvariant_to_json_array (GVariant *variant)
142 array = json_array_new ();
143 json_node = json_node_new (JSON_NODE_ARRAY);
144 json_node_set_array (json_node, array);
145 json_array_unref (array);
147 gvariant_foreach (variant,
148 gvariant_to_json_array_foreach,
155 gvariant_simple_to_string (GVariant *variant)
160 class = g_variant_classify (variant);
163 case G_VARIANT_CLASS_BOOLEAN:
164 if (g_variant_get_boolean (variant))
165 str = g_strdup ("true");
167 str = g_strdup ("false");
170 case G_VARIANT_CLASS_BYTE:
171 str = g_strdup_printf ("%u", g_variant_get_byte (variant));
173 case G_VARIANT_CLASS_INT16:
174 str = g_strdup_printf ("%d", g_variant_get_int16 (variant));
176 case G_VARIANT_CLASS_UINT16:
177 str = g_strdup_printf ("%u", g_variant_get_uint16 (variant));
179 case G_VARIANT_CLASS_INT32:
180 str = g_strdup_printf ("%d", g_variant_get_int32 (variant));
182 case G_VARIANT_CLASS_UINT32:
183 str = g_strdup_printf ("%u", g_variant_get_uint32 (variant));
185 case G_VARIANT_CLASS_INT64:
186 str = g_strdup_printf ("%" G_GINT64_FORMAT,
187 g_variant_get_int64 (variant));
189 case G_VARIANT_CLASS_UINT64:
190 str = g_strdup_printf ("%" G_GUINT64_FORMAT,
191 g_variant_get_uint64 (variant));
193 case G_VARIANT_CLASS_HANDLE:
194 str = g_strdup_printf ("%d", g_variant_get_handle (variant));
197 case G_VARIANT_CLASS_DOUBLE:
199 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
201 g_ascii_formatd (buf,
202 G_ASCII_DTOSTR_BUF_SIZE,
204 g_variant_get_double (variant));
206 str = g_strdup (buf);
210 case G_VARIANT_CLASS_STRING:
211 case G_VARIANT_CLASS_OBJECT_PATH:
212 case G_VARIANT_CLASS_SIGNATURE:
213 str = g_strdup (g_variant_get_string (variant, NULL));
217 g_assert_not_reached ();
225 gvariant_dict_entry_to_json (GVariant *variant, gchar **member_name)
231 member = g_variant_get_child_value (variant, 0);
232 *member_name = gvariant_simple_to_string (member);
234 value = g_variant_get_child_value (variant, 1);
235 json_node = json_gvariant_serialize (value);
237 g_variant_unref (member);
238 g_variant_unref (value);
244 gvariant_to_json_object_foreach (GVariant *variant_child, gpointer user_data)
247 JsonNode *json_child;
248 JsonObject *object = (JsonObject *) user_data;
250 json_child = gvariant_dict_entry_to_json (variant_child, &member_name);
251 json_object_set_member (object, member_name, json_child);
252 g_free (member_name);
256 gvariant_to_json_object (GVariant *variant)
261 json_node = json_node_new (JSON_NODE_OBJECT);
262 object = json_object_new ();
263 json_node_set_object (json_node, object);
264 json_object_unref (object);
266 gvariant_foreach (variant,
267 gvariant_to_json_object_foreach,
274 * json_gvariant_serialize:
275 * @variant: A #GVariant to convert
277 * Converts @variant to a JSON tree.
279 * Return value: (transfer full): A #JsonNode representing the root of the
280 * JSON data structure obtained from @variant
285 json_gvariant_serialize (GVariant *variant)
287 JsonNode *json_node = NULL;
290 g_return_val_if_fail (variant != NULL, NULL);
292 class = g_variant_classify (variant);
294 if (! g_variant_is_container (variant))
296 json_node = json_node_new (JSON_NODE_VALUE);
300 case G_VARIANT_CLASS_BOOLEAN:
301 json_node_set_boolean (json_node, g_variant_get_boolean (variant));
304 case G_VARIANT_CLASS_BYTE:
305 json_node_set_int (json_node, g_variant_get_byte (variant));
307 case G_VARIANT_CLASS_INT16:
308 json_node_set_int (json_node, g_variant_get_int16 (variant));
310 case G_VARIANT_CLASS_UINT16:
311 json_node_set_int (json_node, g_variant_get_uint16 (variant));
313 case G_VARIANT_CLASS_INT32:
314 json_node_set_int (json_node, g_variant_get_int32 (variant));
316 case G_VARIANT_CLASS_UINT32:
317 json_node_set_int (json_node, g_variant_get_uint32 (variant));
319 case G_VARIANT_CLASS_INT64:
320 json_node_set_int (json_node, g_variant_get_int64 (variant));
322 case G_VARIANT_CLASS_UINT64:
323 json_node_set_int (json_node, g_variant_get_uint64 (variant));
325 case G_VARIANT_CLASS_HANDLE:
326 json_node_set_int (json_node, g_variant_get_handle (variant));
329 case G_VARIANT_CLASS_DOUBLE:
330 json_node_set_double (json_node, g_variant_get_double (variant));
333 case G_VARIANT_CLASS_STRING:
334 case G_VARIANT_CLASS_OBJECT_PATH:
335 case G_VARIANT_CLASS_SIGNATURE:
336 json_node_set_string (json_node, g_variant_get_string (variant, NULL));
347 case G_VARIANT_CLASS_MAYBE:
351 value = g_variant_get_maybe (variant);
354 json_node = json_node_new (JSON_NODE_NULL);
358 json_node = json_gvariant_serialize (value);
359 g_variant_unref (value);
365 case G_VARIANT_CLASS_VARIANT:
369 value = g_variant_get_variant (variant);
370 json_node = json_gvariant_serialize (value);
371 g_variant_unref (value);
376 case G_VARIANT_CLASS_ARRAY:
380 type = g_variant_get_type_string (variant);
382 if (type[1] == G_VARIANT_CLASS_DICT_ENTRY)
384 /* array of dictionary entries => JsonObject */
385 json_node = gvariant_to_json_object (variant);
389 /* array of anything else => JsonArray */
390 json_node = gvariant_to_json_array (variant);
396 case G_VARIANT_CLASS_DICT_ENTRY:
402 /* a single dictionary entry => JsonObject */
403 json_node = json_node_new (JSON_NODE_OBJECT);
404 object = json_object_new ();
405 json_node_set_object (json_node, object);
406 json_object_unref (object);
408 child = gvariant_dict_entry_to_json (variant, &member_name);
410 json_object_set_member (object, member_name, child);
411 g_free (member_name);
416 case G_VARIANT_CLASS_TUPLE:
417 json_node = gvariant_to_json_array (variant);
429 * json_gvariant_serialize_data:
430 * @variant: A #GVariant to convert
431 * @length: (out) (allow-none): Return location for the length of the returned
434 * Converts @variant to its JSON encoded string representation. This method
435 * is actually a helper function. It uses json_gvariant_serialize() to obtain the
436 * JSON tree, and then #JsonGenerator to stringify it.
438 * Return value: (transfer full): The JSON encoded string corresponding to
444 json_gvariant_serialize_data (GVariant *variant, gsize *length)
447 JsonGenerator *generator;
450 json_node = json_gvariant_serialize (variant);
452 generator = json_generator_new ();
454 json_generator_set_root (generator, json_node);
455 json = json_generator_to_data (generator, length);
457 g_object_unref (generator);
459 json_node_free (json_node);
464 /* ========================================================================== */
465 /* JSON to GVariant */
466 /* ========================================================================== */
469 json_to_gvariant_get_next_class (JsonNode *json_node,
470 const gchar **signature)
472 if (signature == NULL)
474 GVariantClass class = 0;
476 switch (json_node_get_node_type (json_node))
478 case JSON_NODE_VALUE:
479 switch (json_node_get_value_type (json_node))
482 class = G_VARIANT_CLASS_BOOLEAN;
486 class = G_VARIANT_CLASS_INT64;
490 class = G_VARIANT_CLASS_DOUBLE;
494 class = G_VARIANT_CLASS_STRING;
500 case JSON_NODE_ARRAY:
501 class = G_VARIANT_CLASS_ARRAY;
504 case JSON_NODE_OBJECT:
505 class = JSON_G_VARIANT_CLASS_DICTIONARY;
509 class = G_VARIANT_CLASS_MAYBE;
517 if ((*signature)[0] == G_VARIANT_CLASS_ARRAY &&
518 (*signature)[1] == G_VARIANT_CLASS_DICT_ENTRY)
519 return JSON_G_VARIANT_CLASS_DICTIONARY;
521 return (*signature)[0];
526 json_node_assert_type (JsonNode *json_node,
531 if (JSON_NODE_TYPE (json_node) != type ||
532 (type == JSON_NODE_VALUE &&
533 (json_node_get_value_type (json_node) != sub_type)))
535 /* translators: the '%s' is the type name */
538 G_IO_ERROR_INVALID_DATA,
539 _("Unexpected type '%s' in JSON node"),
540 g_type_name (json_node_get_value_type (json_node)));
550 json_to_gvariant_foreach_add (gpointer data, gpointer user_data)
552 GVariantBuilder *builder = (GVariantBuilder *) user_data;
553 GVariant *child = (GVariant *) data;
555 g_variant_builder_add_value (builder, child);
559 json_to_gvariant_foreach_free (gpointer data, gpointer user_data)
561 GVariant *child = (GVariant *) data;
563 g_variant_unref (child);
567 json_to_gvariant_build_from_glist (GList *list, const gchar *signature)
569 GVariantBuilder *builder;
572 builder = g_variant_builder_new (G_VARIANT_TYPE (signature));
574 g_list_foreach (list, json_to_gvariant_foreach_add, builder);
575 result = g_variant_builder_end (builder);
577 g_variant_builder_unref (builder);
583 json_to_gvariant_tuple (JsonNode *json_node,
584 const gchar **signature,
587 GVariant *variant = NULL;
590 GList *children = NULL;
591 gboolean roll_back = FALSE;
592 const gchar *initial_signature;
594 array = json_node_get_array (json_node);
596 initial_signature = *signature;
599 while ((*signature)[0] != ')' && (*signature)[0] != '\0')
601 JsonNode *json_child;
602 GVariant *variant_child;
604 if (i - 1 >= json_array_get_length (array))
606 g_set_error_literal (error,
608 G_IO_ERROR_INVALID_DATA,
609 _("Missing elements in JSON array to conform to a tuple"));
614 json_child = json_array_get_element (array, i - 1);
616 variant_child = json_to_gvariant_recurse (json_child, signature, error);
617 if (variant_child != NULL)
619 children = g_list_append (children, variant_child);
632 if ( (*signature)[0] != ')')
634 g_set_error_literal (error,
636 G_IO_ERROR_INVALID_DATA,
637 _("Missing closing symbol ')' in the GVariant tuple type"));
640 else if (json_array_get_length (array) >= i)
642 g_set_error_literal (error,
644 G_IO_ERROR_INVALID_DATA,
645 _("Unexpected extra elements in JSON array"));
652 tuple_type = g_strndup (initial_signature,
653 (*signature) - initial_signature + 1);
655 variant = json_to_gvariant_build_from_glist (children, tuple_type);
662 g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
664 g_list_free (children);
670 signature_get_next_complete_type (const gchar **signature)
673 const gchar *initial_signature;
676 /* here it is assumed that 'signature' is a valid type string */
678 initial_signature = *signature;
679 class = (*signature)[0];
681 if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY)
683 gchar stack[256] = {0};
688 if ( (*signature)[0] == G_VARIANT_CLASS_TUPLE)
690 stack[stack_len] = ')';
693 else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY)
695 stack[stack_len] = '}';
701 if ( (*signature)[0] == stack[stack_len - 1])
704 while (stack_len > 0);
708 else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE)
713 tmp_sig = signature_get_next_complete_type (signature);
721 result = g_strndup (initial_signature, (*signature) - initial_signature);
727 json_to_gvariant_maybe (JsonNode *json_node,
728 const gchar **signature,
731 GVariant *variant = NULL;
733 gchar *maybe_signature;
738 maybe_signature = signature_get_next_complete_type (signature);
742 maybe_signature = g_strdup ("v");
745 if (json_node_get_node_type (json_node) == JSON_NODE_NULL)
747 variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), NULL);
751 const gchar *tmp_signature;
753 tmp_signature = maybe_signature;
754 value = json_to_gvariant_recurse (json_node,
759 variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), value);
762 g_free (maybe_signature);
764 /* compensate the (*signature)++ call at the end of 'recurse()' */
772 json_to_gvariant_array (JsonNode *json_node,
773 const gchar **signature,
776 GVariant *variant = NULL;
778 GList *children = NULL;
779 gboolean roll_back = FALSE;
780 const gchar *orig_signature;
781 gchar *child_signature;
783 array = json_node_get_array (json_node);
785 if (signature != NULL)
787 orig_signature = *signature;
790 child_signature = signature_get_next_complete_type (signature);
793 child_signature = g_strdup ("v");
795 if (json_array_get_length (array) > 0)
800 len = json_array_get_length (array);
801 for (i = 0; i < len; i++)
803 JsonNode *json_child;
804 GVariant *variant_child;
805 const gchar *tmp_signature;
807 json_child = json_array_get_element (array, i);
809 tmp_signature = child_signature;
810 variant_child = json_to_gvariant_recurse (json_child,
813 if (variant_child != NULL)
815 children = g_list_append (children, variant_child);
827 gchar *array_signature;
830 array_signature = g_strndup (orig_signature, (*signature) - orig_signature);
832 array_signature = g_strdup ("av");
834 variant = json_to_gvariant_build_from_glist (children, array_signature);
836 g_free (array_signature);
838 /* compensate the (*signature)++ call at the end of 'recurse()' */
843 g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
845 g_list_free (children);
846 g_free (child_signature);
852 gvariant_simple_from_string (const gchar *st,
856 GVariant *variant = NULL;
863 case G_VARIANT_CLASS_BOOLEAN:
864 if (g_strcmp0 (st, "true") == 0)
865 variant = g_variant_new_boolean (TRUE);
866 else if (g_strcmp0 (st, "false") == 0)
867 variant = g_variant_new_boolean (FALSE);
872 case G_VARIANT_CLASS_BYTE:
873 variant = g_variant_new_byte (g_ascii_strtoll (st, &nptr, 10));
876 case G_VARIANT_CLASS_INT16:
877 variant = g_variant_new_int16 (g_ascii_strtoll (st, &nptr, 10));
880 case G_VARIANT_CLASS_UINT16:
881 variant = g_variant_new_uint16 (g_ascii_strtoll (st, &nptr, 10));
884 case G_VARIANT_CLASS_INT32:
885 variant = g_variant_new_int32 (g_ascii_strtoll (st, &nptr, 10));
888 case G_VARIANT_CLASS_UINT32:
889 variant = g_variant_new_uint32 (g_ascii_strtoull (st, &nptr, 10));
892 case G_VARIANT_CLASS_INT64:
893 variant = g_variant_new_int64 (g_ascii_strtoll (st, &nptr, 10));
896 case G_VARIANT_CLASS_UINT64:
897 variant = g_variant_new_uint64 (g_ascii_strtoull (st, &nptr, 10));
900 case G_VARIANT_CLASS_HANDLE:
901 variant = g_variant_new_handle (strtol (st, &nptr, 10));
904 case G_VARIANT_CLASS_DOUBLE:
905 variant = g_variant_new_double (g_ascii_strtod (st, &nptr));
908 case G_VARIANT_CLASS_STRING:
909 case G_VARIANT_CLASS_OBJECT_PATH:
910 case G_VARIANT_CLASS_SIGNATURE:
911 variant = g_variant_new_string (st);
915 g_assert_not_reached ();
919 if (errno != 0 || nptr == st)
921 g_set_error_literal (error,
923 G_IO_ERROR_INVALID_DATA,
924 _("Invalid string value converting to GVariant"));
927 g_variant_unref (variant);
936 parse_dict_entry_signature (const gchar **signature,
937 gchar **entry_signature,
938 gchar **key_signature,
939 gchar **value_signature)
941 const gchar *tmp_sig;
943 if (signature != NULL)
944 *entry_signature = signature_get_next_complete_type (signature);
946 *entry_signature = g_strdup ("{sv}");
948 tmp_sig = (*entry_signature) + 1;
949 *key_signature = signature_get_next_complete_type (&tmp_sig);
950 *value_signature = signature_get_next_complete_type (&tmp_sig);
954 json_to_gvariant_dict_entry (JsonNode *json_node,
955 const gchar **signature,
958 GVariant *variant = NULL;
961 gchar *entry_signature;
962 gchar *key_signature;
963 gchar *value_signature;
964 const gchar *tmp_signature;
968 const gchar *json_member;
969 JsonNode *json_value;
970 GVariant *variant_member;
971 GVariant *variant_value;
973 obj = json_node_get_object (json_node);
975 if (json_object_get_size (obj) != 1)
977 g_set_error_literal (error,
979 G_IO_ERROR_INVALID_DATA,
980 _("A GVariant dictionary entry expects a JSON object with exactly one member"));
984 parse_dict_entry_signature (signature,
989 member = json_object_get_members (obj);
991 json_member = (const gchar *) member->data;
992 variant_member = gvariant_simple_from_string (json_member,
995 if (variant_member != NULL)
997 json_value = json_object_get_member (obj, json_member);
999 tmp_signature = value_signature;
1000 variant_value = json_to_gvariant_recurse (json_value,
1004 if (variant_value != NULL)
1006 GVariantBuilder *builder;
1008 builder = g_variant_builder_new (G_VARIANT_TYPE (entry_signature));
1009 g_variant_builder_add_value (builder, variant_member);
1010 g_variant_builder_add_value (builder, variant_value);
1011 variant = g_variant_builder_end (builder);
1013 g_variant_builder_unref (builder);
1017 g_list_free (member);
1018 g_free (value_signature);
1019 g_free (key_signature);
1020 g_free (entry_signature);
1022 /* compensate the (*signature)++ call at the end of 'recurse()' */
1030 json_to_gvariant_dictionary (JsonNode *json_node,
1031 const gchar **signature,
1034 GVariant *variant = NULL;
1036 gboolean roll_back = FALSE;
1038 gchar *dict_signature;
1039 gchar *entry_signature;
1040 gchar *key_signature;
1041 gchar *value_signature;
1042 const gchar *tmp_signature;
1044 GVariantBuilder *builder;
1048 obj = json_node_get_object (json_node);
1050 if (signature != NULL)
1053 parse_dict_entry_signature (signature,
1058 dict_signature = g_strdup_printf ("a%s", entry_signature);
1060 builder = g_variant_builder_new (G_VARIANT_TYPE (dict_signature));
1062 members = json_object_get_members (obj);
1065 while (member != NULL)
1067 const gchar *json_member;
1068 JsonNode *json_value;
1069 GVariant *variant_member;
1070 GVariant *variant_value;
1072 json_member = (const gchar *) member->data;
1073 variant_member = gvariant_simple_from_string (json_member,
1076 if (variant_member == NULL)
1082 json_value = json_object_get_member (obj, json_member);
1084 tmp_signature = value_signature;
1085 variant_value = json_to_gvariant_recurse (json_value,
1089 if (variant_value != NULL)
1091 g_variant_builder_open (builder, G_VARIANT_TYPE (entry_signature));
1092 g_variant_builder_add_value (builder, variant_member);
1093 g_variant_builder_add_value (builder, variant_value);
1094 g_variant_builder_close (builder);
1102 member = member->next;
1106 variant = g_variant_builder_end (builder);
1108 g_variant_builder_unref (builder);
1109 g_list_free (members);
1110 g_free (value_signature);
1111 g_free (key_signature);
1112 g_free (entry_signature);
1113 g_free (dict_signature);
1115 /* compensate the (*signature)++ call at the end of 'recurse()' */
1116 if (signature != NULL)
1123 json_to_gvariant_recurse (JsonNode *json_node,
1124 const gchar **signature,
1127 GVariant *variant = NULL;
1128 GVariantClass class;
1130 class = json_to_gvariant_get_next_class (json_node, signature);
1132 if (class == JSON_G_VARIANT_CLASS_DICTIONARY)
1134 if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1135 variant = json_to_gvariant_dictionary (json_node, signature, error);
1142 case G_VARIANT_CLASS_BOOLEAN:
1143 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
1144 variant = g_variant_new_boolean (json_node_get_boolean (json_node));
1147 case G_VARIANT_CLASS_BYTE:
1148 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1149 variant = g_variant_new_byte (json_node_get_int (json_node));
1152 case G_VARIANT_CLASS_INT16:
1153 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1154 variant = g_variant_new_int16 (json_node_get_int (json_node));
1157 case G_VARIANT_CLASS_UINT16:
1158 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1159 variant = g_variant_new_uint16 (json_node_get_int (json_node));
1162 case G_VARIANT_CLASS_INT32:
1163 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1164 variant = g_variant_new_int32 (json_node_get_int (json_node));
1167 case G_VARIANT_CLASS_UINT32:
1168 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1169 variant = g_variant_new_uint32 (json_node_get_int (json_node));
1172 case G_VARIANT_CLASS_INT64:
1173 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1174 variant = g_variant_new_int64 (json_node_get_int (json_node));
1177 case G_VARIANT_CLASS_UINT64:
1178 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1179 variant = g_variant_new_uint64 (json_node_get_int (json_node));
1182 case G_VARIANT_CLASS_HANDLE:
1183 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1184 variant = g_variant_new_handle (json_node_get_int (json_node));
1187 case G_VARIANT_CLASS_DOUBLE:
1188 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
1189 variant = g_variant_new_double (json_node_get_double (json_node));
1192 case G_VARIANT_CLASS_STRING:
1193 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1194 variant = g_variant_new_string (json_node_get_string (json_node));
1197 case G_VARIANT_CLASS_OBJECT_PATH:
1198 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1199 variant = g_variant_new_object_path (json_node_get_string (json_node));
1202 case G_VARIANT_CLASS_SIGNATURE:
1203 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1204 variant = g_variant_new_signature (json_node_get_string (json_node));
1207 case G_VARIANT_CLASS_VARIANT:
1208 variant = g_variant_new_variant (json_to_gvariant_recurse (json_node,
1213 case G_VARIANT_CLASS_MAYBE:
1214 variant = json_to_gvariant_maybe (json_node, signature, error);
1217 case G_VARIANT_CLASS_ARRAY:
1218 if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1219 variant = json_to_gvariant_array (json_node, signature, error);
1222 case G_VARIANT_CLASS_TUPLE:
1223 if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1224 variant = json_to_gvariant_tuple (json_node, signature, error);
1227 case G_VARIANT_CLASS_DICT_ENTRY:
1228 if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1229 variant = json_to_gvariant_dict_entry (json_node, signature, error);
1235 G_IO_ERROR_INVALID_DATA,
1236 _("GVariant class '%c' not supported"), class);
1248 * json_gvariant_deserialize:
1249 * @json_node: A #JsonNode to convert
1250 * @signature: (allow-none): A valid #GVariant type string, or %NULL
1251 * @error: A pointer to a #GError
1253 * Converts a JSON data structure to a GVariant value using @signature to
1254 * resolve ambiguous data types. If no error occurs, the resulting #GVariant
1255 * is guaranteed to conform to @signature.
1257 * If @signature is not %NULL but does not represent a valid GVariant type
1258 * string, %NULL is returned and error is set to %G_IO_ERROR_INVALID_ARGUMENT.
1259 * If a @signature is provided but the JSON structure cannot be mapped to it,
1260 * %NULL is returned and error is set to %G_IO_ERROR_INVALID_DATA.
1261 * If @signature is %NULL, the conversion is done based strictly on the types
1262 * in the JSON nodes.
1264 * Return value: (transfer full): A newly created #GVariant compliant with
1265 * @signature, or %NULL on error
1270 json_gvariant_deserialize (JsonNode *json_node,
1271 const gchar *signature,
1274 g_return_val_if_fail (json_node != NULL, NULL);
1276 if (signature != NULL && ! g_variant_type_string_is_valid (signature))
1278 g_set_error_literal (error,
1280 G_IO_ERROR_INVALID_ARGUMENT,
1281 _("Invalid GVariant signature"));
1285 return json_to_gvariant_recurse (json_node, signature ? &signature : NULL, error);
1289 * json_gvariant_deserialize_data:
1290 * @json: A JSON data string
1291 * @length: The length of @json, or -1 if %NULL-terminated
1292 * @signature: (allow-none): A valid #GVariant type string, or %NULL
1293 * @error: A pointer to a #GError
1295 * Converts a JSON string to a #GVariant value. This method works exactly
1296 * like json_gvariant_deserialize(), but takes a JSON encoded string instead.
1297 * The string is first converted to a #JsonNode using #JsonParser, and then
1298 * json_gvariant_deserialize() is called.
1300 * Returns: (transfer full): A newly created #GVariant compliant with
1301 * @signature, or %NULL on error
1306 json_gvariant_deserialize_data (const gchar *json,
1308 const gchar *signature,
1312 GVariant *variant = NULL;
1315 parser = json_parser_new ();
1317 if (! json_parser_load_from_data (parser, json, length, error))
1320 root = json_parser_get_root (parser);
1323 g_set_error_literal (error,
1325 G_IO_ERROR_INVALID_DATA,
1326 _("JSON data is empty"));
1331 json_gvariant_deserialize (json_parser_get_root (parser), signature, error);
1334 g_object_unref (parser);