1 /* json-gobject.c - JSON GObject 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 * Emmanuele Bassi <ebassi@openedhand.com>
21 * SECTION:json-gobject
22 * @short_description: Serialize and deserialize GObjects
24 * JSON-GLib provides API for serializing and deserializing #GObject<!-- -->s
25 * to and from JSON data streams.
27 * Simple #GObject classes can be (de)serialized into JSON objects, if the
28 * properties have compatible types with the native JSON types (integers,
29 * booleans, strings, string vectors). If the class to be (de)serialized has
30 * complex data types for properties (like boxed types or other objects)
31 * then the class should implement the provided #JsonSerializable interface
32 * and its virtual functions.
42 #include <glib/gi18n-lib.h>
44 #include "json-types-private.h"
45 #include "json-gobject-private.h"
47 #include "json-debug.h"
48 #include "json-parser.h"
49 #include "json-generator.h"
52 enum_from_string (GType type,
60 gboolean retval = TRUE;
62 g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
63 g_return_val_if_fail (string != NULL, 0);
65 value = strtoul (string, &endptr, 0);
66 if (endptr != string) /* parsed a number */
70 eclass = g_type_class_ref (type);
71 ev = g_enum_get_value_by_name (eclass, string);
73 ev = g_enum_get_value_by_nick (eclass, string);
76 *enum_value = ev->value;
80 g_type_class_unref (eclass);
87 flags_from_string (GType type,
92 gchar *endptr, *prevptr;
93 guint i, j, ret, value;
100 g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
101 g_return_val_if_fail (string != 0, 0);
105 value = strtoul (string, &endptr, 0);
106 if (endptr != string) /* parsed a number */
107 *flags_value = value;
110 fclass = g_type_class_ref (type);
112 flagstr = g_strdup (string);
113 for (value = i = j = 0; ; i++)
115 eos = flagstr[i] == '\0';
117 if (!eos && flagstr[i] != '|')
121 endptr = &flagstr[i];
132 ch = g_utf8_get_char (flag);
133 if (!g_unichar_isspace (ch))
135 flag = g_utf8_next_char (flag);
138 while (endptr > flag)
140 prevptr = g_utf8_prev_char (endptr);
141 ch = g_utf8_get_char (prevptr);
142 if (!g_unichar_isspace (ch))
150 fv = g_flags_get_value_by_name (fclass, flag);
153 fv = g_flags_get_value_by_nick (fclass, flag);
166 *flags_value = value;
173 g_type_class_unref (fclass);
180 json_gobject_new (GType gtype,
183 JsonSerializableIface *iface = NULL;
184 JsonSerializable *serializable = NULL;
185 gboolean find_property;
186 gboolean deserialize_property;
187 gboolean set_property;
188 GList *members, *members_left, *l;
192 GArray *construct_params;
195 klass = g_type_class_ref (gtype);
197 n_members = json_object_get_size (object);
198 members = json_object_get_members (object);
201 /* first pass: construct-only properties; here we cannot use Serializable
202 * because we don't have an instance yet; we use the default implementation
203 * of json_deserialize_pspec() to deserialize known types
205 * FIXME - find a way to allow deserialization for these properties
207 construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
209 for (l = members; l != NULL; l = l->next)
211 const gchar *member_name = l->data;
213 GParameter param = { NULL, };
215 gboolean res = FALSE;
217 pspec = g_object_class_find_property (klass, member_name);
221 /* we only apply construct-only properties here */
222 if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0)
225 if (!(pspec->flags & G_PARAM_WRITABLE))
228 g_value_init (¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
230 val = json_object_get_member (object, member_name);
231 res = json_deserialize_pspec (¶m.value, pspec, val);
234 g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
235 pspec->name, G_VALUE_TYPE_NAME (¶m.value), g_type_name (gtype));
237 g_value_unset (¶m.value);
241 param.name = g_strdup (pspec->name);
243 g_array_append_val (construct_params, param);
249 members_left = g_list_prepend (members_left, l->data);
252 retval = g_object_newv (gtype,
253 construct_params->len,
254 (GParameter *) construct_params->data);
256 /* free the contents of the GArray */
257 for (i = 0; i < construct_params->len; i++)
259 GParameter *param = &g_array_index (construct_params, GParameter, i);
261 g_free ((gchar *) param->name);
262 g_value_unset (¶m->value);
265 g_array_free (construct_params, TRUE);
266 g_list_free (members);
268 /* we use g_list_prepend() above, but we want to maintain
269 * the ordering of json_object_get_members() here
271 members = g_list_reverse (members_left);
273 /* do the Serializable type check once */
274 if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
276 serializable = JSON_SERIALIZABLE (retval);
277 iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
278 find_property = (iface->find_property != NULL);
279 deserialize_property = (iface->deserialize_property != NULL);
280 set_property = (iface->set_property != NULL);
284 find_property = FALSE;
285 deserialize_property = FALSE;
286 set_property = FALSE;
289 g_object_freeze_notify (retval);
291 for (l = members; l != NULL; l = l->next)
293 const gchar *member_name = l->data;
296 GValue value = { 0, };
297 gboolean res = FALSE;
300 pspec = json_serializable_find_property (serializable, member_name);
302 pspec = g_object_class_find_property (klass, member_name);
307 /* we should have dealt with these above */
308 if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
311 if (!(pspec->flags & G_PARAM_WRITABLE))
314 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
316 val = json_object_get_member (object, member_name);
318 if (deserialize_property)
320 JSON_NOTE (GOBJECT, "Using JsonSerializable for property '%s'", pspec->name);
321 res = iface->deserialize_property (serializable, pspec->name,
329 JSON_NOTE (GOBJECT, "Using json_deserialize_pspec for property '%s'", pspec->name);
330 res = json_deserialize_pspec (&value, pspec, val);
335 JSON_NOTE (GOBJECT, "Calling set_property('%s', '%s')",
337 g_type_name (G_VALUE_TYPE (&value)));
340 json_serializable_set_property (serializable, pspec, &value);
342 g_object_set_property (retval, pspec->name, &value);
345 g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
346 pspec->name, g_type_name (G_VALUE_TYPE (&value)), g_type_name (gtype));
348 g_value_unset (&value);
351 g_list_free (members);
353 g_object_thaw_notify (retval);
355 g_type_class_unref (klass);
361 json_gobject_dump (GObject *gobject)
363 JsonSerializableIface *iface = NULL;
364 JsonSerializable *serializable = NULL;
365 gboolean list_properties = FALSE;
366 gboolean serialize_property = FALSE;
367 gboolean get_property = FALSE;
372 if (JSON_IS_SERIALIZABLE (gobject))
374 serializable = JSON_SERIALIZABLE (gobject);
375 iface = JSON_SERIALIZABLE_GET_IFACE (gobject);
376 list_properties = (iface->list_properties != NULL);
377 serialize_property = (iface->serialize_property != NULL);
378 get_property = (iface->get_property != NULL);
381 object = json_object_new ();
384 pspecs = json_serializable_list_properties (serializable, &n_pspecs);
386 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (gobject), &n_pspecs);
388 for (i = 0; i < n_pspecs; i++)
390 GParamSpec *pspec = pspecs[i];
391 GValue value = { 0, };
392 JsonNode *node = NULL;
394 /* read only what we can */
395 if (!(pspec->flags & G_PARAM_READABLE))
398 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
401 json_serializable_get_property (serializable, pspec, &value);
403 g_object_get_property (gobject, pspec->name, &value);
405 /* if there is a serialization vfunc, then it is completely responsible
406 * for serializing the property, possibly by calling the implementation
407 * of the default JsonSerializable interface through chaining up
409 if (serialize_property)
411 node = iface->serialize_property (serializable, pspec->name,
415 /* skip if the value is the default for the property */
416 else if (!g_param_value_defaults (pspec, &value))
417 node = json_serialize_pspec (&value, pspec);
420 json_object_set_member (object, pspec->name, node);
422 g_value_unset (&value);
431 json_deserialize_pspec (GValue *value,
435 GValue node_value = { 0, };
436 gboolean retval = FALSE;
438 if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_BOXED)
440 JsonNodeType node_type = json_node_get_node_type (node);
441 GType boxed_type = G_VALUE_TYPE (value);
443 if (json_boxed_can_deserialize (boxed_type, node_type))
445 gpointer boxed = json_boxed_deserialize (boxed_type, node);
447 g_value_take_boxed (value, boxed);
453 switch (JSON_NODE_TYPE (node))
455 case JSON_NODE_OBJECT:
456 if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT))
460 object = json_gobject_new (G_VALUE_TYPE (value), json_node_get_object (node));
462 g_value_take_object (value, object);
464 g_value_set_object (value, NULL);
470 case JSON_NODE_ARRAY:
471 if (G_VALUE_HOLDS (value, G_TYPE_STRV))
473 JsonArray *array = json_node_get_array (node);
474 guint i, array_len = json_array_get_length (array);
475 GPtrArray *str_array = g_ptr_array_sized_new (array_len + 1);
477 for (i = 0; i < array_len; i++)
479 JsonNode *val = json_array_get_element (array, i);
481 if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE)
484 if (json_node_get_string (val) != NULL)
485 g_ptr_array_add (str_array, (gpointer) json_node_get_string (val));
488 g_ptr_array_add (str_array, NULL);
490 g_value_set_boxed (value, str_array->pdata);
492 g_ptr_array_free (str_array, TRUE);
498 case JSON_NODE_VALUE:
499 json_node_get_value (node, &node_value);
502 gchar *node_str = g_strdup_value_contents (&node_value);
503 g_debug ("%s: value type '%s' := node value type '%s' -> '%s'",
505 g_type_name (G_VALUE_TYPE (value)),
506 g_type_name (G_VALUE_TYPE (&node_value)),
512 switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
517 if (G_VALUE_HOLDS (&node_value, G_VALUE_TYPE (value)))
519 g_value_copy (&node_value, value);
525 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
527 g_value_set_int (value, (gint) g_value_get_int64 (&node_value));
533 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
535 #if GLIB_CHECK_VERSION (2, 31, 0)
536 g_value_set_schar (value, (gchar) g_value_get_int64 (&node_value));
538 g_value_set_char (value, (gchar) g_value_get_int64 (&node_value));
545 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
547 g_value_set_uint (value, (guint) g_value_get_int64 (&node_value));
553 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
555 g_value_set_uchar (value, (guchar) g_value_get_int64 (&node_value));
562 if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
564 g_value_set_double (value, g_value_get_double (&node_value));
567 else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
569 g_value_set_double (value, (gdouble) g_value_get_int64 (&node_value));
576 if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
578 g_value_set_float (value, (gfloat) g_value_get_double (&node_value));
581 else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
583 g_value_set_float (value, (gfloat) g_value_get_int64 (&node_value));
593 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
595 enum_value = g_value_get_int64 (&node_value);
598 else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
600 retval = enum_from_string (G_VALUE_TYPE (value),
601 g_value_get_string (&node_value),
606 g_value_set_enum (value, enum_value);
612 gint flags_value = 0;
614 if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
616 flags_value = g_value_get_int64 (&node_value);
619 else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
621 retval = flags_from_string (G_VALUE_TYPE (value),
622 g_value_get_string (&node_value),
627 g_value_set_flags (value, flags_value);
636 g_value_unset (&node_value);
640 if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING)
642 g_value_set_string (value, NULL);
645 else if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_OBJECT)
647 g_value_set_object (value, NULL);
660 json_serialize_pspec (const GValue *real_value,
663 JsonNode *retval = NULL;
664 GValue value = { 0, };
665 JsonNodeType node_type;
667 switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (real_value)))
672 /* JSON native types */
673 retval = json_node_new (JSON_NODE_VALUE);
674 g_value_init (&value, G_VALUE_TYPE (real_value));
675 g_value_copy (real_value, &value);
676 json_node_set_value (retval, &value);
677 g_value_unset (&value);
681 /* strings might be NULL, so we handle it differently */
682 if (!g_value_get_string (real_value))
683 retval = json_node_new (JSON_NODE_NULL);
686 retval = json_node_new (JSON_NODE_VALUE);
687 json_node_set_string (retval, g_value_get_string (real_value));
693 retval = json_node_new (JSON_NODE_VALUE);
694 json_node_set_int (retval, g_value_get_int (real_value));
698 retval = json_node_new (JSON_NODE_VALUE);
699 json_node_set_double (retval, g_value_get_float (real_value));
703 if (G_VALUE_HOLDS (real_value, G_TYPE_STRV))
705 gchar **strv = g_value_get_boxed (real_value);
709 strv_len = g_strv_length (strv);
710 array = json_array_sized_new (strv_len);
712 for (i = 0; i < strv_len; i++)
714 JsonNode *str = json_node_new (JSON_NODE_VALUE);
716 json_node_set_string (str, strv[i]);
717 json_array_add_element (array, str);
720 retval = json_node_new (JSON_NODE_ARRAY);
721 json_node_take_array (retval, array);
723 else if (json_boxed_can_serialize (G_VALUE_TYPE (real_value), &node_type))
725 gpointer boxed = g_value_get_boxed (real_value);
727 retval = json_boxed_serialize (G_VALUE_TYPE (real_value), boxed);
730 g_warning ("Boxed type '%s' is not handled by JSON-GLib",
731 g_type_name (G_VALUE_TYPE (real_value)));
735 retval = json_node_new (JSON_NODE_VALUE);
736 json_node_set_int (retval, g_value_get_uint (real_value));
740 retval = json_node_new (JSON_NODE_VALUE);
741 json_node_set_int (retval, g_value_get_long (real_value));
745 retval = json_node_new (JSON_NODE_VALUE);
746 json_node_set_int (retval, g_value_get_long (real_value));
750 retval = json_node_new (JSON_NODE_VALUE);
751 #if GLIB_CHECK_VERSION (2, 31, 0)
752 json_node_set_int (retval, g_value_get_schar (real_value));
754 json_node_set_int (retval, g_value_get_char (real_value));
759 retval = json_node_new (JSON_NODE_VALUE);
760 json_node_set_int (retval, g_value_get_uchar (real_value));
764 retval = json_node_new (JSON_NODE_VALUE);
765 json_node_set_int (retval, g_value_get_enum (real_value));
769 retval = json_node_new (JSON_NODE_VALUE);
770 json_node_set_int (retval, g_value_get_flags (real_value));
775 GObject *object = g_value_get_object (real_value);
779 retval = json_node_new (JSON_NODE_OBJECT);
780 json_node_take_object (retval, json_gobject_dump (object));
783 retval = json_node_new (JSON_NODE_NULL);
788 retval = json_node_new (JSON_NODE_NULL);
792 g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
800 * json_gobject_deserialize:
801 * @gtype: the type of the #GObject to create
802 * @node: a #JsonNode of type %JSON_NODE_OBJECT describing the
803 * instance of type @gtype
805 * Creates a new #GObject of type @gtype, and constructs it
806 * using the members of the passed #JsonObject
808 * Return value: (transfer full): The newly created #GObject
809 * instance. Use g_object_unref() to free the resources
810 * allocated by this function
815 json_gobject_deserialize (GType gtype,
818 g_return_val_if_fail (g_type_is_a (gtype, G_TYPE_OBJECT), NULL);
819 g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
821 return json_gobject_new (gtype, json_node_get_object (node));
825 * json_gobject_serialize:
826 * @gobject: a #GObject
828 * Creates a #JsonNode representing the passed #GObject
829 * instance. Each member of the returned JSON object will
830 * map to a property of the #GObject
832 * Return value: (transfer full): the newly created #JsonNode
833 * of type %JSON_NODE_OBJECT. Use json_node_free() to free
834 * the resources allocated by this function
839 json_gobject_serialize (GObject *gobject)
843 g_return_val_if_fail (G_IS_OBJECT (gobject), NULL);
845 retval = json_node_new (JSON_NODE_OBJECT);
846 json_node_take_object (retval, json_gobject_dump (gobject));
852 * json_construct_gobject:
853 * @gtype: the #GType of object to construct
854 * @data: a JSON data stream
855 * @length: length of the data stream
856 * @error: return location for a #GError, or %NULL
858 * Deserializes a JSON data stream and creates the corresponding
859 * #GObject class. If @gtype implements the #JsonSerializableIface
860 * interface, it will be asked to deserialize all the JSON members
861 * into the respective properties; otherwise, the default implementation
862 * will be used to translate the compatible JSON native types.
864 * Note: the JSON data stream must be an object declaration.
866 * Return value: (transfer full): a #GObject or %NULL
870 * Deprecated: 0.10: Use json_gobject_from_data() instead
873 json_construct_gobject (GType gtype,
878 return json_gobject_from_data (gtype, data, strlen (data), error);
882 * json_gobject_from_data:
883 * @gtype: the #GType of object to construct
884 * @data: a JSON data stream
885 * @length: length of the data stream, or -1 if it is NUL-terminated
886 * @error: return location for a #GError, or %NULL
888 * Deserializes a JSON data stream and creates the corresponding
889 * #GObject class. If @gtype implements the #JsonSerializableIface
890 * interface, it will be asked to deserialize all the JSON members
891 * into the respective properties; otherwise, the default implementation
892 * will be used to translate the compatible JSON native types.
894 * Note: the JSON data stream must be an object declaration.
896 * Return value: (transfer full): a #GObject or %NULL
901 json_gobject_from_data (GType gtype,
911 g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
912 g_return_val_if_fail (data != NULL, NULL);
915 length = strlen (data);
917 parser = json_parser_new ();
920 json_parser_load_from_data (parser, data, length, &parse_error);
923 g_propagate_error (error, parse_error);
924 g_object_unref (parser);
928 root = json_parser_get_root (parser);
929 if (root == NULL || JSON_NODE_TYPE (root) != JSON_NODE_OBJECT)
931 /* translators: the %s is the name of the data structure */
932 g_set_error (error, JSON_PARSER_ERROR,
933 JSON_PARSER_ERROR_PARSE,
934 _("Expecting a JSON object, but the root node is of type `%s'"),
935 json_node_type_name (root));
936 g_object_unref (parser);
940 retval = json_gobject_deserialize (gtype, root);
942 g_object_unref (parser);
948 * json_serialize_gobject:
949 * @gobject: a #GObject
950 * @length: (out): return value for the length of the buffer, or %NULL
952 * Serializes a #GObject into a JSON data stream. If @gobject implements
953 * the #JsonSerializableIface interface, it will be asked to serizalize all
954 * its properties; otherwise, the default implementation will be use to
955 * translate the compatible types into JSON native types.
957 * Return value: a JSON data stream representing the passed #GObject
959 * Deprecated: 0.10: Use json_gobject_to_data() instead
962 json_serialize_gobject (GObject *gobject,
965 return json_gobject_to_data (gobject, length);
969 * json_gobject_to_data:
970 * @gobject: a #GObject
971 * @length: (out): return value for the length of the buffer, or %NULL
973 * Serializes a #GObject into a JSON data stream, iterating recursively
974 * over each property.
976 * If @gobject implements the #JsonSerializableIface interface, it will
977 * be asked to serialize all its properties; otherwise, the default
978 * implementation will be use to translate the compatible types into
981 * Return value: a JSON data stream representing the passed #GObject
986 json_gobject_to_data (GObject *gobject,
993 g_return_val_if_fail (G_OBJECT (gobject), NULL);
995 root = json_gobject_serialize (gobject);
997 gen = g_object_new (JSON_TYPE_GENERATOR,
1003 data = json_generator_to_data (gen, length);
1004 g_object_unref (gen);
1006 json_node_free (root);