1 /* json-gvariant.c - JSON GVariant integration
2 *
3 * This file is part of JSON-GLib
4 * Copyright (C) 2007 OpenedHand Ltd.
5 *
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.
10 *
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.
15 *
16 * Author:
17 * Eduardo Lima Mitev <elima@igalia.com>
18 */
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25
26 #include <glib/gi18n-lib.h>
27
28 #include <gio/gio.h>
29
30 #include "json-gvariant.h"
31
32 #include "json-generator.h"
33 #include "json-parser.h"
34 #include "json-types-private.h"
35
36 /**
37 * SECTION:json-gvariant
38 * @short_description: Serialize and deserialize GVariant types
39 * @Title: JSON GVariant Integration
40 *
41 * Use json_gvariant_serialize() and json_gvariant_serialize_data() to
42 * convert from any #GVariant value to a #JsonNode tree or its string
43 * representation.
44 *
45 * Use json_gvariant_deserialize() and json_gvariant_deserialize_data() to
46 * obtain the #GVariant value from a #JsonNode tree or directly from a JSON
47 * string.
48 *
49 * Since many #GVariant data types cannot be directly represented as
50 * JSON, a #GVariant type string (signature) should be provided to these
51 * methods in order to obtain a correct, type-contrained result.
52 * If no signature is provided, conversion can still be done, but the
53 * resulting #GVariant value will be "guessed" from the JSON data types
54 * using the following rules:
55 *
56 * ## Strings
57 * JSON strings map to GVariant `(s)`.
58 *
59 * ## Integers
60 * JSON integers map to GVariant int64 `(x)`.
61 *
62 * ## Booleans
63 * JSON booleans map to GVariant boolean `(b)`.
64 *
65 * ## Numbers
66 * JSON numbers map to GVariant double `(d)`.
67 *
68 * ## Arrays
69 * JSON arrays map to GVariant arrays of variants `(av)`.
70 *
71 * ## Objects
72 * JSON objects map to GVariant dictionaries of string to variants `(a{sv})`.
73 *
74 * ## Null values
75 * JSON null values map to GVariant maybe variants `(mv)`.
76 */
77
78 /* custom extension to the GVariantClass enumeration to differentiate
79 * a single dictionary entry from an array of dictionary entries
80 */
81 #define JSON_G_VARIANT_CLASS_DICTIONARY 'c'
82
83 typedef void (* GVariantForeachFunc) (GVariant *variant_child,
84 gpointer user_data);
85
86 static GVariant * json_to_gvariant_recurse (JsonNode *json_node,
87 const gchar **signature,
88 GError **error);
89
90 /* ========================================================================== */
91 /* GVariant to JSON */
92 /* ========================================================================== */
93
94 static void
gvariant_foreach(GVariant * variant,GVariantForeachFunc func,gpointer user_data)95 gvariant_foreach (GVariant *variant,
96 GVariantForeachFunc func,
97 gpointer user_data)
98 {
99 GVariantIter iter;
100 GVariant *variant_child;
101
102 g_variant_iter_init (&iter, variant);
103 while ((variant_child = g_variant_iter_next_value (&iter)) != NULL)
104 {
105 func (variant_child, user_data);
106 g_variant_unref (variant_child);
107 }
108 }
109
110 static void
gvariant_to_json_array_foreach(GVariant * variant_child,gpointer user_data)111 gvariant_to_json_array_foreach (GVariant *variant_child,
112 gpointer user_data)
113 {
114 JsonArray *array = user_data;
115 JsonNode *json_child;
116
117 json_child = json_gvariant_serialize (variant_child);
118 json_array_add_element (array, json_child);
119 }
120
121 static JsonNode *
gvariant_to_json_array(GVariant * variant)122 gvariant_to_json_array (GVariant *variant)
123 {
124 JsonArray *array;
125 JsonNode *json_node;
126
127 array = json_array_new ();
128 json_node = json_node_new (JSON_NODE_ARRAY);
129 json_node_set_array (json_node, array);
130 json_array_unref (array);
131
132 gvariant_foreach (variant,
133 gvariant_to_json_array_foreach,
134 array);
135
136 return json_node;
137 }
138
139 static gchar *
gvariant_simple_to_string(GVariant * variant)140 gvariant_simple_to_string (GVariant *variant)
141 {
142 GVariantClass class;
143 gchar *str;
144
145 class = g_variant_classify (variant);
146 switch (class)
147 {
148 case G_VARIANT_CLASS_BOOLEAN:
149 if (g_variant_get_boolean (variant))
150 str = g_strdup ("true");
151 else
152 str = g_strdup ("false");
153 break;
154
155 case G_VARIANT_CLASS_BYTE:
156 str = g_strdup_printf ("%u", g_variant_get_byte (variant));
157 break;
158 case G_VARIANT_CLASS_INT16:
159 str = g_strdup_printf ("%d", g_variant_get_int16 (variant));
160 break;
161 case G_VARIANT_CLASS_UINT16:
162 str = g_strdup_printf ("%u", g_variant_get_uint16 (variant));
163 break;
164 case G_VARIANT_CLASS_INT32:
165 str = g_strdup_printf ("%d", g_variant_get_int32 (variant));
166 break;
167 case G_VARIANT_CLASS_UINT32:
168 str = g_strdup_printf ("%u", g_variant_get_uint32 (variant));
169 break;
170 case G_VARIANT_CLASS_INT64:
171 str = g_strdup_printf ("%" G_GINT64_FORMAT,
172 g_variant_get_int64 (variant));
173 break;
174 case G_VARIANT_CLASS_UINT64:
175 str = g_strdup_printf ("%" G_GUINT64_FORMAT,
176 g_variant_get_uint64 (variant));
177 break;
178 case G_VARIANT_CLASS_HANDLE:
179 str = g_strdup_printf ("%d", g_variant_get_handle (variant));
180 break;
181
182 case G_VARIANT_CLASS_DOUBLE:
183 {
184 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
185
186 g_ascii_formatd (buf,
187 G_ASCII_DTOSTR_BUF_SIZE,
188 "%f",
189 g_variant_get_double (variant));
190
191 str = g_strdup (buf);
192 break;
193 }
194
195 case G_VARIANT_CLASS_STRING:
196 case G_VARIANT_CLASS_OBJECT_PATH:
197 case G_VARIANT_CLASS_SIGNATURE:
198 str = g_strdup (g_variant_get_string (variant, NULL));
199 break;
200
201 default:
202 g_assert_not_reached ();
203 break;
204 }
205
206 return str;
207 }
208
209 static JsonNode *
gvariant_dict_entry_to_json(GVariant * variant,gchar ** member_name)210 gvariant_dict_entry_to_json (GVariant *variant, gchar **member_name)
211 {
212 GVariant *member;
213 GVariant *value;
214 JsonNode *json_node;
215
216 member = g_variant_get_child_value (variant, 0);
217 *member_name = gvariant_simple_to_string (member);
218
219 value = g_variant_get_child_value (variant, 1);
220 json_node = json_gvariant_serialize (value);
221
222 g_variant_unref (member);
223 g_variant_unref (value);
224
225 return json_node;
226 }
227
228 static void
gvariant_to_json_object_foreach(GVariant * variant_child,gpointer user_data)229 gvariant_to_json_object_foreach (GVariant *variant_child, gpointer user_data)
230 {
231 gchar *member_name;
232 JsonNode *json_child;
233 JsonObject *object = (JsonObject *) user_data;
234
235 json_child = gvariant_dict_entry_to_json (variant_child, &member_name);
236 json_object_set_member (object, member_name, json_child);
237 g_free (member_name);
238 }
239
240 static JsonNode *
gvariant_to_json_object(GVariant * variant)241 gvariant_to_json_object (GVariant *variant)
242 {
243 JsonNode *json_node;
244 JsonObject *object;
245
246 json_node = json_node_new (JSON_NODE_OBJECT);
247 object = json_object_new ();
248 json_node_set_object (json_node, object);
249 json_object_unref (object);
250
251 gvariant_foreach (variant,
252 gvariant_to_json_object_foreach,
253 object);
254
255 return json_node;
256 }
257
258 /**
259 * json_gvariant_serialize:
260 * @variant: A #GVariant to convert
261 *
262 * Converts @variant to a JSON tree.
263 *
264 * Return value: (transfer full): A #JsonNode representing the root of the
265 * JSON data structure obtained from @variant
266 *
267 * Since: 0.14
268 */
269 JsonNode *
json_gvariant_serialize(GVariant * variant)270 json_gvariant_serialize (GVariant *variant)
271 {
272 JsonNode *json_node = NULL;
273 GVariantClass class;
274
275 g_return_val_if_fail (variant != NULL, NULL);
276
277 class = g_variant_classify (variant);
278
279 if (! g_variant_is_container (variant))
280 {
281 json_node = json_node_new (JSON_NODE_VALUE);
282
283 switch (class)
284 {
285 case G_VARIANT_CLASS_BOOLEAN:
286 json_node_set_boolean (json_node, g_variant_get_boolean (variant));
287 break;
288
289 case G_VARIANT_CLASS_BYTE:
290 json_node_set_int (json_node, g_variant_get_byte (variant));
291 break;
292 case G_VARIANT_CLASS_INT16:
293 json_node_set_int (json_node, g_variant_get_int16 (variant));
294 break;
295 case G_VARIANT_CLASS_UINT16:
296 json_node_set_int (json_node, g_variant_get_uint16 (variant));
297 break;
298 case G_VARIANT_CLASS_INT32:
299 json_node_set_int (json_node, g_variant_get_int32 (variant));
300 break;
301 case G_VARIANT_CLASS_UINT32:
302 json_node_set_int (json_node, g_variant_get_uint32 (variant));
303 break;
304 case G_VARIANT_CLASS_INT64:
305 json_node_set_int (json_node, g_variant_get_int64 (variant));
306 break;
307 case G_VARIANT_CLASS_UINT64:
308 json_node_set_int (json_node, g_variant_get_uint64 (variant));
309 break;
310 case G_VARIANT_CLASS_HANDLE:
311 json_node_set_int (json_node, g_variant_get_handle (variant));
312 break;
313
314 case G_VARIANT_CLASS_DOUBLE:
315 json_node_set_double (json_node, g_variant_get_double (variant));
316 break;
317
318 case G_VARIANT_CLASS_STRING:
319 case G_VARIANT_CLASS_OBJECT_PATH:
320 case G_VARIANT_CLASS_SIGNATURE:
321 json_node_set_string (json_node, g_variant_get_string (variant, NULL));
322 break;
323
324 default:
325 break;
326 }
327 }
328 else
329 {
330 switch (class)
331 {
332 case G_VARIANT_CLASS_MAYBE:
333 {
334 GVariant *value;
335
336 value = g_variant_get_maybe (variant);
337 if (value == NULL)
338 {
339 json_node = json_node_new (JSON_NODE_NULL);
340 }
341 else
342 {
343 json_node = json_gvariant_serialize (value);
344 g_variant_unref (value);
345 }
346
347 break;
348 }
349
350 case G_VARIANT_CLASS_VARIANT:
351 {
352 GVariant *value;
353
354 value = g_variant_get_variant (variant);
355 json_node = json_gvariant_serialize (value);
356 g_variant_unref (value);
357
358 break;
359 }
360
361 case G_VARIANT_CLASS_ARRAY:
362 {
363 const gchar *type;
364
365 type = g_variant_get_type_string (variant);
366
367 if (type[1] == G_VARIANT_CLASS_DICT_ENTRY)
368 {
369 /* array of dictionary entries => JsonObject */
370 json_node = gvariant_to_json_object (variant);
371 }
372 else
373 {
374 /* array of anything else => JsonArray */
375 json_node = gvariant_to_json_array (variant);
376 }
377
378 break;
379 }
380
381 case G_VARIANT_CLASS_DICT_ENTRY:
382 {
383 gchar *member_name;
384 JsonObject *object;
385 JsonNode *child;
386
387 /* a single dictionary entry => JsonObject */
388 json_node = json_node_new (JSON_NODE_OBJECT);
389 object = json_object_new ();
390 json_node_set_object (json_node, object);
391 json_object_unref (object);
392
393 child = gvariant_dict_entry_to_json (variant, &member_name);
394
395 json_object_set_member (object, member_name, child);
396 g_free (member_name);
397
398 break;
399 }
400
401 case G_VARIANT_CLASS_TUPLE:
402 json_node = gvariant_to_json_array (variant);
403 break;
404
405 default:
406 break;
407 }
408 }
409
410 return json_node;
411 }
412
413 /**
414 * json_gvariant_serialize_data:
415 * @variant: A #GVariant to convert
416 * @length: (out) (allow-none): Return location for the length of the returned
417 * string, or %NULL
418 *
419 * Converts @variant to its JSON encoded string representation. This method
420 * is actually a helper function. It uses json_gvariant_serialize() to obtain the
421 * JSON tree, and then #JsonGenerator to stringify it.
422 *
423 * Return value: (transfer full): The JSON encoded string corresponding to
424 * @variant
425 *
426 * Since: 0.14
427 */
428 gchar *
json_gvariant_serialize_data(GVariant * variant,gsize * length)429 json_gvariant_serialize_data (GVariant *variant, gsize *length)
430 {
431 JsonNode *json_node;
432 JsonGenerator *generator;
433 gchar *json;
434
435 json_node = json_gvariant_serialize (variant);
436
437 generator = json_generator_new ();
438
439 json_generator_set_root (generator, json_node);
440 json = json_generator_to_data (generator, length);
441
442 g_object_unref (generator);
443
444 json_node_unref (json_node);
445
446 return json;
447 }
448
449 /* ========================================================================== */
450 /* JSON to GVariant */
451 /* ========================================================================== */
452
453 static GVariantClass
json_to_gvariant_get_next_class(JsonNode * json_node,const gchar ** signature)454 json_to_gvariant_get_next_class (JsonNode *json_node,
455 const gchar **signature)
456 {
457 if (signature == NULL)
458 {
459 GVariantClass class = 0;
460
461 switch (json_node_get_node_type (json_node))
462 {
463 case JSON_NODE_VALUE:
464 switch (json_node_get_value_type (json_node))
465 {
466 case G_TYPE_BOOLEAN:
467 class = G_VARIANT_CLASS_BOOLEAN;
468 break;
469
470 case G_TYPE_INT64:
471 class = G_VARIANT_CLASS_INT64;
472 break;
473
474 case G_TYPE_DOUBLE:
475 class = G_VARIANT_CLASS_DOUBLE;
476 break;
477
478 case G_TYPE_STRING:
479 class = G_VARIANT_CLASS_STRING;
480 break;
481 }
482
483 break;
484
485 case JSON_NODE_ARRAY:
486 class = G_VARIANT_CLASS_ARRAY;
487 break;
488
489 case JSON_NODE_OBJECT:
490 class = JSON_G_VARIANT_CLASS_DICTIONARY;
491 break;
492
493 case JSON_NODE_NULL:
494 class = G_VARIANT_CLASS_MAYBE;
495 break;
496 }
497
498 return class;
499 }
500 else
501 {
502 if ((*signature)[0] == G_VARIANT_CLASS_ARRAY &&
503 (*signature)[1] == G_VARIANT_CLASS_DICT_ENTRY)
504 return JSON_G_VARIANT_CLASS_DICTIONARY;
505 else
506 return (*signature)[0];
507 }
508 }
509
510 static gboolean
json_node_assert_type(JsonNode * json_node,JsonNodeType type,GType sub_type,GError ** error)511 json_node_assert_type (JsonNode *json_node,
512 JsonNodeType type,
513 GType sub_type,
514 GError **error)
515 {
516 if (JSON_NODE_TYPE (json_node) != type ||
517 (type == JSON_NODE_VALUE &&
518 (json_node_get_value_type (json_node) != sub_type)))
519 {
520 g_set_error (error,
521 G_IO_ERROR,
522 G_IO_ERROR_INVALID_DATA,
523 /* translators: the '%s' is the type name */
524 _("Unexpected type “%s” in JSON node"),
525 g_type_name (json_node_get_value_type (json_node)));
526 return FALSE;
527 }
528 else
529 {
530 return TRUE;
531 }
532 }
533
534 static void
json_to_gvariant_foreach_add(gpointer data,gpointer user_data)535 json_to_gvariant_foreach_add (gpointer data, gpointer user_data)
536 {
537 GVariantBuilder *builder = (GVariantBuilder *) user_data;
538 GVariant *child = (GVariant *) data;
539
540 g_variant_builder_add_value (builder, child);
541 }
542
543 static void
json_to_gvariant_foreach_free(gpointer data,gpointer user_data)544 json_to_gvariant_foreach_free (gpointer data, gpointer user_data)
545 {
546 GVariant *child = (GVariant *) data;
547
548 g_variant_unref (child);
549 }
550
551 static GVariant *
json_to_gvariant_build_from_glist(GList * list,const gchar * signature)552 json_to_gvariant_build_from_glist (GList *list, const gchar *signature)
553 {
554 GVariantBuilder *builder;
555 GVariant *result;
556
557 builder = g_variant_builder_new (G_VARIANT_TYPE (signature));
558
559 g_list_foreach (list, json_to_gvariant_foreach_add, builder);
560 result = g_variant_builder_end (builder);
561
562 g_variant_builder_unref (builder);
563
564 return result;
565 }
566
567 static GVariant *
json_to_gvariant_tuple(JsonNode * json_node,const gchar ** signature,GError ** error)568 json_to_gvariant_tuple (JsonNode *json_node,
569 const gchar **signature,
570 GError **error)
571 {
572 GVariant *variant = NULL;
573 JsonArray *array;
574 gint i;
575 GList *children = NULL;
576 gboolean roll_back = FALSE;
577 const gchar *initial_signature;
578
579 array = json_node_get_array (json_node);
580
581 initial_signature = *signature;
582 (*signature)++;
583 i = 1;
584 while ((*signature)[0] != ')' && (*signature)[0] != '\0')
585 {
586 JsonNode *json_child;
587 GVariant *variant_child;
588
589 if (i - 1 >= json_array_get_length (array))
590 {
591 g_set_error_literal (error,
592 G_IO_ERROR,
593 G_IO_ERROR_INVALID_DATA,
594 _("Missing elements in JSON array to conform to a tuple"));
595 roll_back = TRUE;
596 break;
597 }
598
599 json_child = json_array_get_element (array, i - 1);
600
601 variant_child = json_to_gvariant_recurse (json_child, signature, error);
602 if (variant_child != NULL)
603 {
604 children = g_list_append (children, variant_child);
605 }
606 else
607 {
608 roll_back = TRUE;
609 break;
610 }
611
612 i++;
613 }
614
615 if (! roll_back)
616 {
617 if ( (*signature)[0] != ')')
618 {
619 g_set_error_literal (error,
620 G_IO_ERROR,
621 G_IO_ERROR_INVALID_DATA,
622 _("Missing closing symbol “)” in the GVariant tuple type"));
623 roll_back = TRUE;
624 }
625 else if (json_array_get_length (array) >= i)
626 {
627 g_set_error_literal (error,
628 G_IO_ERROR,
629 G_IO_ERROR_INVALID_DATA,
630 _("Unexpected extra elements in JSON array"));
631 roll_back = TRUE;
632 }
633 else
634 {
635 gchar *tuple_type;
636
637 tuple_type = g_strndup (initial_signature,
638 (*signature) - initial_signature + 1);
639
640 variant = json_to_gvariant_build_from_glist (children, tuple_type);
641
642 g_free (tuple_type);
643 }
644 }
645
646 if (roll_back)
647 g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
648
649 g_list_free (children);
650
651 return variant;
652 }
653
654 static gchar *
signature_get_next_complete_type(const gchar ** signature)655 signature_get_next_complete_type (const gchar **signature)
656 {
657 GVariantClass class;
658 const gchar *initial_signature;
659 gchar *result;
660
661 /* here it is assumed that 'signature' is a valid type string */
662
663 initial_signature = *signature;
664 class = (*signature)[0];
665
666 if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY)
667 {
668 gchar stack[256] = {0};
669 guint stack_len = 0;
670
671 do
672 {
673 if ( (*signature)[0] == G_VARIANT_CLASS_TUPLE)
674 {
675 stack[stack_len] = ')';
676 stack_len++;
677 }
678 else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY)
679 {
680 stack[stack_len] = '}';
681 stack_len++;
682 }
683
684 (*signature)++;
685
686 if ( (*signature)[0] == stack[stack_len - 1])
687 stack_len--;
688 }
689 while (stack_len > 0);
690
691 (*signature)++;
692 }
693 else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE)
694 {
695 gchar *tmp_sig;
696
697 (*signature)++;
698 tmp_sig = signature_get_next_complete_type (signature);
699 g_free (tmp_sig);
700 }
701 else
702 {
703 (*signature)++;
704 }
705
706 result = g_strndup (initial_signature, (*signature) - initial_signature);
707
708 return result;
709 }
710
711 static GVariant *
json_to_gvariant_maybe(JsonNode * json_node,const gchar ** signature,GError ** error)712 json_to_gvariant_maybe (JsonNode *json_node,
713 const gchar **signature,
714 GError **error)
715 {
716 GVariant *variant = NULL;
717 GVariant *value;
718 gchar *maybe_signature;
719
720 if (signature)
721 {
722 (*signature)++;
723 maybe_signature = signature_get_next_complete_type (signature);
724 }
725 else
726 {
727 maybe_signature = g_strdup ("v");
728 }
729
730 if (json_node_get_node_type (json_node) == JSON_NODE_NULL)
731 {
732 variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), NULL);
733 }
734 else
735 {
736 const gchar *tmp_signature;
737
738 tmp_signature = maybe_signature;
739 value = json_to_gvariant_recurse (json_node,
740 &tmp_signature,
741 error);
742
743 if (value != NULL)
744 variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), value);
745 }
746
747 g_free (maybe_signature);
748
749 /* compensate the (*signature)++ call at the end of 'recurse()' */
750 if (signature)
751 (*signature)--;
752
753 return variant;
754 }
755
756 static GVariant *
json_to_gvariant_array(JsonNode * json_node,const gchar ** signature,GError ** error)757 json_to_gvariant_array (JsonNode *json_node,
758 const gchar **signature,
759 GError **error)
760 {
761 GVariant *variant = NULL;
762 JsonArray *array;
763 GList *children = NULL;
764 gboolean roll_back = FALSE;
765 const gchar *orig_signature = NULL;
766 gchar *child_signature;
767
768 array = json_node_get_array (json_node);
769
770 if (signature != NULL)
771 {
772 orig_signature = *signature;
773
774 (*signature)++;
775 child_signature = signature_get_next_complete_type (signature);
776 }
777 else
778 child_signature = g_strdup ("v");
779
780 if (json_array_get_length (array) > 0)
781 {
782 gint i;
783 guint len;
784
785 len = json_array_get_length (array);
786 for (i = 0; i < len; i++)
787 {
788 JsonNode *json_child;
789 GVariant *variant_child;
790 const gchar *tmp_signature;
791
792 json_child = json_array_get_element (array, i);
793
794 tmp_signature = child_signature;
795 variant_child = json_to_gvariant_recurse (json_child,
796 &tmp_signature,
797 error);
798 if (variant_child != NULL)
799 {
800 children = g_list_append (children, variant_child);
801 }
802 else
803 {
804 roll_back = TRUE;
805 break;
806 }
807 }
808 }
809
810 if (!roll_back)
811 {
812 gchar *array_signature;
813
814 if (signature)
815 array_signature = g_strndup (orig_signature, (*signature) - orig_signature);
816 else
817 array_signature = g_strdup ("av");
818
819 variant = json_to_gvariant_build_from_glist (children, array_signature);
820
821 g_free (array_signature);
822
823 /* compensate the (*signature)++ call at the end of 'recurse()' */
824 if (signature)
825 (*signature)--;
826 }
827 else
828 g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
829
830 g_list_free (children);
831 g_free (child_signature);
832
833 return variant;
834 }
835
836 static GVariant *
gvariant_simple_from_string(const gchar * st,GVariantClass class,GError ** error)837 gvariant_simple_from_string (const gchar *st,
838 GVariantClass class,
839 GError **error)
840 {
841 GVariant *variant = NULL;
842 gchar *nptr = NULL;
843 gboolean conversion_error = FALSE;
844 gint64 signed_value;
845 guint64 unsigned_value;
846 gdouble double_value;
847
848 errno = 0;
849
850 switch (class)
851 {
852 case G_VARIANT_CLASS_BOOLEAN:
853 if (g_strcmp0 (st, "true") == 0)
854 variant = g_variant_new_boolean (TRUE);
855 else if (g_strcmp0 (st, "false") == 0)
856 variant = g_variant_new_boolean (FALSE);
857 else
858 conversion_error = TRUE;
859 break;
860
861 case G_VARIANT_CLASS_BYTE:
862 signed_value = g_ascii_strtoll (st, &nptr, 10);
863 conversion_error = errno != 0 || nptr == st;
864 variant = g_variant_new_byte (signed_value);
865 break;
866
867 case G_VARIANT_CLASS_INT16:
868 signed_value = g_ascii_strtoll (st, &nptr, 10);
869 conversion_error = errno != 0 || nptr == st;
870 variant = g_variant_new_int16 (signed_value);
871 break;
872
873 case G_VARIANT_CLASS_UINT16:
874 signed_value = g_ascii_strtoll (st, &nptr, 10);
875 conversion_error = errno != 0 || nptr == st;
876 variant = g_variant_new_uint16 (signed_value);
877 break;
878
879 case G_VARIANT_CLASS_INT32:
880 signed_value = g_ascii_strtoll (st, &nptr, 10);
881 conversion_error = errno != 0 || nptr == st;
882 variant = g_variant_new_int32 (signed_value);
883 break;
884
885 case G_VARIANT_CLASS_UINT32:
886 unsigned_value = g_ascii_strtoull (st, &nptr, 10);
887 conversion_error = errno != 0 || nptr == st;
888 variant = g_variant_new_uint32 (unsigned_value);
889 break;
890
891 case G_VARIANT_CLASS_INT64:
892 signed_value = g_ascii_strtoll (st, &nptr, 10);
893 conversion_error = errno != 0 || nptr == st;
894 variant = g_variant_new_int64 (signed_value);
895 break;
896
897 case G_VARIANT_CLASS_UINT64:
898 unsigned_value = g_ascii_strtoull (st, &nptr, 10);
899 conversion_error = errno != 0 || nptr == st;
900 variant = g_variant_new_uint64 (unsigned_value);
901 break;
902
903 case G_VARIANT_CLASS_HANDLE:
904 signed_value = strtol (st, &nptr, 10);
905 conversion_error = errno != 0 || nptr == st;
906 variant = g_variant_new_handle (signed_value);
907 break;
908
909 case G_VARIANT_CLASS_DOUBLE:
910 double_value = g_ascii_strtod (st, &nptr);
911 conversion_error = errno != 0 || nptr == st;
912 variant = g_variant_new_double (double_value);
913 break;
914
915 case G_VARIANT_CLASS_STRING:
916 case G_VARIANT_CLASS_OBJECT_PATH:
917 case G_VARIANT_CLASS_SIGNATURE:
918 variant = g_variant_new_string (st);
919 break;
920
921 default:
922 g_assert_not_reached ();
923 break;
924 }
925
926 if (conversion_error)
927 {
928 g_set_error_literal (error,
929 G_IO_ERROR,
930 G_IO_ERROR_INVALID_DATA,
931 _("Invalid string value converting to GVariant"));
932 if (variant != NULL)
933 {
934 g_variant_unref (variant);
935 variant = NULL;
936 }
937 }
938
939 return variant;
940 }
941
942 static void
parse_dict_entry_signature(const gchar ** signature,gchar ** entry_signature,gchar ** key_signature,gchar ** value_signature)943 parse_dict_entry_signature (const gchar **signature,
944 gchar **entry_signature,
945 gchar **key_signature,
946 gchar **value_signature)
947 {
948 const gchar *tmp_sig;
949
950 if (signature != NULL)
951 *entry_signature = signature_get_next_complete_type (signature);
952 else
953 *entry_signature = g_strdup ("{sv}");
954
955 tmp_sig = (*entry_signature) + 1;
956 *key_signature = signature_get_next_complete_type (&tmp_sig);
957 *value_signature = signature_get_next_complete_type (&tmp_sig);
958 }
959
960 static GVariant *
json_to_gvariant_dict_entry(JsonNode * json_node,const gchar ** signature,GError ** error)961 json_to_gvariant_dict_entry (JsonNode *json_node,
962 const gchar **signature,
963 GError **error)
964 {
965 GVariant *variant = NULL;
966 JsonObject *obj;
967
968 gchar *entry_signature;
969 gchar *key_signature;
970 gchar *value_signature;
971 const gchar *tmp_signature;
972
973 GQueue *members;
974 const gchar *json_member;
975 JsonNode *json_value;
976 GVariant *variant_member;
977 GVariant *variant_value;
978
979 obj = json_node_get_object (json_node);
980
981 if (json_object_get_size (obj) != 1)
982 {
983 g_set_error_literal (error,
984 G_IO_ERROR,
985 G_IO_ERROR_INVALID_DATA,
986 _("A GVariant dictionary entry expects a JSON object with exactly one member"));
987 return NULL;
988 }
989
990 parse_dict_entry_signature (signature,
991 &entry_signature,
992 &key_signature,
993 &value_signature);
994
995 members = json_object_get_members_internal (obj);
996 json_member = (const gchar *) members->head->data;
997 variant_member = gvariant_simple_from_string (json_member,
998 key_signature[0],
999 error);
1000 if (variant_member != NULL)
1001 {
1002 json_value = json_object_get_member (obj, json_member);
1003
1004 tmp_signature = value_signature;
1005 variant_value = json_to_gvariant_recurse (json_value,
1006 &tmp_signature,
1007 error);
1008
1009 if (variant_value != NULL)
1010 {
1011 GVariantBuilder *builder;
1012
1013 builder = g_variant_builder_new (G_VARIANT_TYPE (entry_signature));
1014 g_variant_builder_add_value (builder, variant_member);
1015 g_variant_builder_add_value (builder, variant_value);
1016 variant = g_variant_builder_end (builder);
1017
1018 g_variant_builder_unref (builder);
1019 }
1020 }
1021
1022 g_free (value_signature);
1023 g_free (key_signature);
1024 g_free (entry_signature);
1025
1026 /* compensate the (*signature)++ call at the end of 'recurse()' */
1027 if (signature)
1028 (*signature)--;
1029
1030 return variant;
1031 }
1032
1033 static GVariant *
json_to_gvariant_dictionary(JsonNode * json_node,const gchar ** signature,GError ** error)1034 json_to_gvariant_dictionary (JsonNode *json_node,
1035 const gchar **signature,
1036 GError **error)
1037 {
1038 GVariant *variant = NULL;
1039 JsonObject *obj;
1040 gboolean roll_back = FALSE;
1041
1042 gchar *dict_signature;
1043 gchar *entry_signature;
1044 gchar *key_signature;
1045 gchar *value_signature;
1046 const gchar *tmp_signature;
1047
1048 GVariantBuilder *builder;
1049 GQueue *members;
1050 GList *member;
1051
1052 obj = json_node_get_object (json_node);
1053
1054 if (signature != NULL)
1055 (*signature)++;
1056
1057 parse_dict_entry_signature (signature,
1058 &entry_signature,
1059 &key_signature,
1060 &value_signature);
1061
1062 dict_signature = g_strdup_printf ("a%s", entry_signature);
1063
1064 builder = g_variant_builder_new (G_VARIANT_TYPE (dict_signature));
1065
1066 members = json_object_get_members_internal (obj);
1067
1068 for (member = members->head; member != NULL; member = member->next)
1069 {
1070 const gchar *json_member;
1071 JsonNode *json_value;
1072 GVariant *variant_member;
1073 GVariant *variant_value;
1074
1075 json_member = (const gchar *) member->data;
1076 variant_member = gvariant_simple_from_string (json_member,
1077 key_signature[0],
1078 error);
1079 if (variant_member == NULL)
1080 {
1081 roll_back = TRUE;
1082 break;
1083 }
1084
1085 json_value = json_object_get_member (obj, json_member);
1086
1087 tmp_signature = value_signature;
1088 variant_value = json_to_gvariant_recurse (json_value,
1089 &tmp_signature,
1090 error);
1091
1092 if (variant_value != NULL)
1093 {
1094 g_variant_builder_open (builder, G_VARIANT_TYPE (entry_signature));
1095 g_variant_builder_add_value (builder, variant_member);
1096 g_variant_builder_add_value (builder, variant_value);
1097 g_variant_builder_close (builder);
1098 }
1099 else
1100 {
1101 roll_back = TRUE;
1102 break;
1103 }
1104 }
1105
1106 if (! roll_back)
1107 variant = g_variant_builder_end (builder);
1108
1109 g_variant_builder_unref (builder);
1110 g_free (value_signature);
1111 g_free (key_signature);
1112 g_free (entry_signature);
1113 g_free (dict_signature);
1114
1115 /* compensate the (*signature)++ call at the end of 'recurse()' */
1116 if (signature != NULL)
1117 (*signature)--;
1118
1119 return variant;
1120 }
1121
1122 static GVariant *
json_to_gvariant_recurse(JsonNode * json_node,const gchar ** signature,GError ** error)1123 json_to_gvariant_recurse (JsonNode *json_node,
1124 const gchar **signature,
1125 GError **error)
1126 {
1127 GVariant *variant = NULL;
1128 GVariantClass class;
1129
1130 class = json_to_gvariant_get_next_class (json_node, signature);
1131
1132 if (class == JSON_G_VARIANT_CLASS_DICTIONARY)
1133 {
1134 if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1135 variant = json_to_gvariant_dictionary (json_node, signature, error);
1136
1137 goto out;
1138 }
1139
1140 if (JSON_NODE_TYPE (json_node) == JSON_NODE_VALUE &&
1141 json_node_get_value_type (json_node) == G_TYPE_STRING)
1142 {
1143 const gchar* str = json_node_get_string (json_node);
1144 switch (class)
1145 {
1146 case G_VARIANT_CLASS_BOOLEAN:
1147 case G_VARIANT_CLASS_BYTE:
1148 case G_VARIANT_CLASS_INT16:
1149 case G_VARIANT_CLASS_UINT16:
1150 case G_VARIANT_CLASS_INT32:
1151 case G_VARIANT_CLASS_UINT32:
1152 case G_VARIANT_CLASS_INT64:
1153 case G_VARIANT_CLASS_UINT64:
1154 case G_VARIANT_CLASS_HANDLE:
1155 case G_VARIANT_CLASS_DOUBLE:
1156 case G_VARIANT_CLASS_STRING:
1157 variant = gvariant_simple_from_string (str, class, error);
1158 goto out;
1159 default:
1160 break;
1161 }
1162 }
1163
1164 switch (class)
1165 {
1166 case G_VARIANT_CLASS_BOOLEAN:
1167 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
1168 variant = g_variant_new_boolean (json_node_get_boolean (json_node));
1169 break;
1170
1171 case G_VARIANT_CLASS_BYTE:
1172 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1173 variant = g_variant_new_byte (json_node_get_int (json_node));
1174 break;
1175
1176 case G_VARIANT_CLASS_INT16:
1177 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1178 variant = g_variant_new_int16 (json_node_get_int (json_node));
1179 break;
1180
1181 case G_VARIANT_CLASS_UINT16:
1182 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1183 variant = g_variant_new_uint16 (json_node_get_int (json_node));
1184 break;
1185
1186 case G_VARIANT_CLASS_INT32:
1187 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1188 variant = g_variant_new_int32 (json_node_get_int (json_node));
1189 break;
1190
1191 case G_VARIANT_CLASS_UINT32:
1192 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1193 variant = g_variant_new_uint32 (json_node_get_int (json_node));
1194 break;
1195
1196 case G_VARIANT_CLASS_INT64:
1197 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1198 variant = g_variant_new_int64 (json_node_get_int (json_node));
1199 break;
1200
1201 case G_VARIANT_CLASS_UINT64:
1202 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1203 variant = g_variant_new_uint64 (json_node_get_int (json_node));
1204 break;
1205
1206 case G_VARIANT_CLASS_HANDLE:
1207 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
1208 variant = g_variant_new_handle (json_node_get_int (json_node));
1209 break;
1210
1211 case G_VARIANT_CLASS_DOUBLE:
1212 /* Doubles can look like ints to the json parser: when they don't have a dot */
1213 if (JSON_NODE_TYPE (json_node) == JSON_NODE_VALUE &&
1214 json_node_get_value_type (json_node) == G_TYPE_INT64)
1215 variant = g_variant_new_double (json_node_get_int (json_node));
1216 else if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
1217 variant = g_variant_new_double (json_node_get_double (json_node));
1218 break;
1219
1220 case G_VARIANT_CLASS_STRING:
1221 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1222 variant = g_variant_new_string (json_node_get_string (json_node));
1223 break;
1224
1225 case G_VARIANT_CLASS_OBJECT_PATH:
1226 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1227 variant = g_variant_new_object_path (json_node_get_string (json_node));
1228 break;
1229
1230 case G_VARIANT_CLASS_SIGNATURE:
1231 if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
1232 variant = g_variant_new_signature (json_node_get_string (json_node));
1233 break;
1234
1235 case G_VARIANT_CLASS_VARIANT:
1236 variant = g_variant_new_variant (json_to_gvariant_recurse (json_node,
1237 NULL,
1238 error));
1239 break;
1240
1241 case G_VARIANT_CLASS_MAYBE:
1242 variant = json_to_gvariant_maybe (json_node, signature, error);
1243 break;
1244
1245 case G_VARIANT_CLASS_ARRAY:
1246 if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1247 variant = json_to_gvariant_array (json_node, signature, error);
1248 break;
1249
1250 case G_VARIANT_CLASS_TUPLE:
1251 if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
1252 variant = json_to_gvariant_tuple (json_node, signature, error);
1253 break;
1254
1255 case G_VARIANT_CLASS_DICT_ENTRY:
1256 if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
1257 variant = json_to_gvariant_dict_entry (json_node, signature, error);
1258 break;
1259
1260 default:
1261 g_set_error (error,
1262 G_IO_ERROR,
1263 G_IO_ERROR_INVALID_DATA,
1264 _("GVariant class “%c” not supported"), class);
1265 break;
1266 }
1267
1268 out:
1269 if (signature)
1270 (*signature)++;
1271
1272 return variant;
1273 }
1274
1275 /**
1276 * json_gvariant_deserialize:
1277 * @json_node: A #JsonNode to convert
1278 * @signature: (allow-none): A valid #GVariant type string, or %NULL
1279 * @error: A pointer to a #GError
1280 *
1281 * Converts a JSON data structure to a GVariant value using @signature to
1282 * resolve ambiguous data types. If no error occurs, the resulting #GVariant
1283 * is guaranteed to conform to @signature.
1284 *
1285 * If @signature is not %NULL but does not represent a valid GVariant type
1286 * string, %NULL is returned and error is set to %G_IO_ERROR_INVALID_ARGUMENT.
1287 * If a @signature is provided but the JSON structure cannot be mapped to it,
1288 * %NULL is returned and error is set to %G_IO_ERROR_INVALID_DATA.
1289 * If @signature is %NULL, the conversion is done based strictly on the types
1290 * in the JSON nodes.
1291 *
1292 * The returned variant has a floating reference that will need to be sunk
1293 * by the caller code.
1294 *
1295 * Return value: (transfer none): A newly created, floating #GVariant
1296 * compliant with @signature, or %NULL on error
1297 *
1298 * Since: 0.14
1299 */
1300 GVariant *
json_gvariant_deserialize(JsonNode * json_node,const gchar * signature,GError ** error)1301 json_gvariant_deserialize (JsonNode *json_node,
1302 const gchar *signature,
1303 GError **error)
1304 {
1305 g_return_val_if_fail (json_node != NULL, NULL);
1306
1307 if (signature != NULL && ! g_variant_type_string_is_valid (signature))
1308 {
1309 g_set_error_literal (error,
1310 G_IO_ERROR,
1311 G_IO_ERROR_INVALID_ARGUMENT,
1312 _("Invalid GVariant signature"));
1313 return NULL;
1314 }
1315
1316 return json_to_gvariant_recurse (json_node, signature ? &signature : NULL, error);
1317 }
1318
1319 /**
1320 * json_gvariant_deserialize_data:
1321 * @json: A JSON data string
1322 * @length: The length of @json, or -1 if %NULL-terminated
1323 * @signature: (allow-none): A valid #GVariant type string, or %NULL
1324 * @error: A pointer to a #GError
1325 *
1326 * Converts a JSON string to a #GVariant value. This method works exactly
1327 * like json_gvariant_deserialize(), but takes a JSON encoded string instead.
1328 * The string is first converted to a #JsonNode using #JsonParser, and then
1329 * json_gvariant_deserialize() is called.
1330 *
1331 * The returned variant has a floating reference that will need to be sunk
1332 * by the caller code.
1333 *
1334 * Returns: (transfer none): A newly created, floating #GVariant compliant
1335 * with @signature, or %NULL on error
1336 *
1337 * Since: 0.14
1338 */
1339 GVariant *
json_gvariant_deserialize_data(const gchar * json,gssize length,const gchar * signature,GError ** error)1340 json_gvariant_deserialize_data (const gchar *json,
1341 gssize length,
1342 const gchar *signature,
1343 GError **error)
1344 {
1345 JsonParser *parser;
1346 GVariant *variant = NULL;
1347 JsonNode *root;
1348
1349 parser = json_parser_new ();
1350
1351 if (! json_parser_load_from_data (parser, json, length, error))
1352 return NULL;
1353
1354 root = json_parser_get_root (parser);
1355 if (root == NULL)
1356 {
1357 g_set_error_literal (error,
1358 G_IO_ERROR,
1359 G_IO_ERROR_INVALID_DATA,
1360 _("JSON data is empty"));
1361 }
1362 else
1363 {
1364 variant =
1365 json_gvariant_deserialize (json_parser_get_root (parser), signature, error);
1366 }
1367
1368 g_object_unref (parser);
1369
1370 return variant;
1371 }
1372