Initial Import
[profile/ivi/json-glib.git] / json-glib / json-gobject.c
1 /* json-gobject.c - JSON GObject 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  *   Emmanuele Bassi  <ebassi@openedhand.com>
18  */
19
20 /**
21  * SECTION:json-gobject
22  * @short_description: Serialize and deserialize GObjects
23  *
24  * JSON-GLib provides API for serializing and deserializing #GObject<!-- -->s
25  * to and from JSON data streams.
26  *
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.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <string.h>
40 #include <stdlib.h>
41
42 #include <glib/gi18n-lib.h>
43
44 #include "json-types-private.h"
45 #include "json-gobject-private.h"
46
47 #include "json-debug.h"
48 #include "json-parser.h"
49 #include "json-generator.h"
50
51 static gboolean
52 enum_from_string (GType        type,
53                   const gchar *string,
54                   gint        *enum_value)
55 {
56   GEnumClass *eclass;
57   GEnumValue *ev;
58   gchar *endptr;
59   gint value;
60   gboolean retval = TRUE;
61
62   g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
63   g_return_val_if_fail (string != NULL, 0);
64
65   value = strtoul (string, &endptr, 0);
66   if (endptr != string) /* parsed a number */
67     *enum_value = value;
68   else
69     {
70       eclass = g_type_class_ref (type);
71       ev = g_enum_get_value_by_name (eclass, string);
72       if (!ev)
73         ev = g_enum_get_value_by_nick (eclass, string);
74
75       if (ev)
76         *enum_value = ev->value;
77       else
78         retval = FALSE;
79
80       g_type_class_unref (eclass);
81     }
82
83   return retval;
84 }
85
86 static gboolean
87 flags_from_string (GType        type,
88                    const gchar *string,
89                    gint        *flags_value)
90 {
91   GFlagsClass *fclass;
92   gchar *endptr, *prevptr;
93   guint i, j, ret, value;
94   gchar *flagstr;
95   GFlagsValue *fv;
96   const gchar *flag;
97   gunichar ch;
98   gboolean eos;
99
100   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
101   g_return_val_if_fail (string != 0, 0);
102
103   ret = TRUE;
104
105   value = strtoul (string, &endptr, 0);
106   if (endptr != string) /* parsed a number */
107     *flags_value = value;
108   else
109     {
110       fclass = g_type_class_ref (type);
111
112       flagstr = g_strdup (string);
113       for (value = i = j = 0; ; i++)
114         {
115           eos = flagstr[i] == '\0';
116
117           if (!eos && flagstr[i] != '|')
118             continue;
119
120           flag = &flagstr[j];
121           endptr = &flagstr[i];
122
123           if (!eos)
124             {
125               flagstr[i++] = '\0';
126               j = i;
127             }
128
129           /* trim spaces */
130           for (;;)
131             {
132               ch = g_utf8_get_char (flag);
133               if (!g_unichar_isspace (ch))
134                 break;
135               flag = g_utf8_next_char (flag);
136             }
137
138           while (endptr > flag)
139             {
140               prevptr = g_utf8_prev_char (endptr);
141               ch = g_utf8_get_char (prevptr);
142               if (!g_unichar_isspace (ch))
143                 break;
144               endptr = prevptr;
145             }
146
147           if (endptr > flag)
148             {
149               *endptr = '\0';
150               fv = g_flags_get_value_by_name (fclass, flag);
151
152               if (!fv)
153                 fv = g_flags_get_value_by_nick (fclass, flag);
154
155               if (fv)
156                 value |= fv->value;
157               else
158                 {
159                   ret = FALSE;
160                   break;
161                 }
162             }
163
164           if (eos)
165             {
166               *flags_value = value;
167               break;
168             }
169         }
170
171       g_free (flagstr);
172
173       g_type_class_unref (fclass);
174     }
175
176   return ret;
177 }
178
179 static GObject *
180 json_gobject_new (GType       gtype,
181                   JsonObject *object)
182 {
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;
189   guint n_members;
190   GObjectClass *klass;
191   GObject *retval;
192   GArray *construct_params;
193   gint i;
194
195   klass = g_type_class_ref (gtype);
196
197   n_members = json_object_get_size (object);
198   members = json_object_get_members (object);
199   members_left = NULL;
200
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
204    *
205    * FIXME - find a way to allow deserialization for these properties
206    */
207   construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
208
209   for (l = members; l != NULL; l = l->next)
210     {
211       const gchar *member_name = l->data;
212       GParamSpec *pspec;
213       GParameter param = { NULL, };
214       JsonNode *val;
215       gboolean res = FALSE;
216
217       pspec = g_object_class_find_property (klass, member_name);
218       if (!pspec)
219         goto next_member;
220
221       /* we only apply construct-only properties here */
222       if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0)
223         goto next_member;
224
225       if (!(pspec->flags & G_PARAM_WRITABLE))
226         goto next_member;
227
228       g_value_init (&param.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
229
230       val = json_object_get_member (object, member_name);
231       res = json_deserialize_pspec (&param.value, pspec, val);
232       if (!res)
233         {
234           g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
235                      pspec->name, G_VALUE_TYPE_NAME (&param.value), g_type_name (gtype));
236
237           g_value_unset (&param.value);
238         }
239       else
240         {
241           param.name = g_strdup (pspec->name);
242
243           g_array_append_val (construct_params, param);
244
245           continue;
246         }
247
248     next_member:
249       members_left = g_list_prepend (members_left, l->data);
250     }
251
252   retval = g_object_newv (gtype,
253                           construct_params->len,
254                           (GParameter *) construct_params->data);
255
256   /* free the contents of the GArray */
257   for (i = 0; i < construct_params->len; i++)
258     {
259       GParameter *param = &g_array_index (construct_params, GParameter, i);
260
261       g_free ((gchar *) param->name);
262       g_value_unset (&param->value);
263     }
264
265   g_array_free (construct_params, TRUE);
266   g_list_free (members);
267
268   /* we use g_list_prepend() above, but we want to maintain
269    * the ordering of json_object_get_members() here
270    */
271   members = g_list_reverse (members_left);
272
273   /* do the Serializable type check once */
274   if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
275     {
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);
281     }
282   else
283     {
284       find_property = FALSE;
285       deserialize_property = FALSE;
286       set_property = FALSE;
287     }
288
289   g_object_freeze_notify (retval);
290
291   for (l = members; l != NULL; l = l->next)
292     {
293       const gchar *member_name = l->data;
294       GParamSpec *pspec;
295       JsonNode *val;
296       GValue value = { 0, };
297       gboolean res = FALSE;
298
299       if (find_property)
300         pspec = json_serializable_find_property (serializable, member_name);
301       else
302         pspec = g_object_class_find_property (klass, member_name);
303
304       if (pspec == NULL)
305         continue;
306
307       /* we should have dealt with these above */
308       if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
309         continue;
310
311       if (!(pspec->flags & G_PARAM_WRITABLE))
312         continue;
313
314       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
315
316       val = json_object_get_member (object, member_name);
317
318       if (deserialize_property)
319         {
320           JSON_NOTE (GOBJECT, "Using JsonSerializable for property '%s'", pspec->name);
321           res = iface->deserialize_property (serializable, pspec->name,
322                                              &value,
323                                              pspec,
324                                              val);
325         }
326
327       if (!res)
328         {
329           JSON_NOTE (GOBJECT, "Using json_deserialize_pspec for property '%s'", pspec->name);
330           res = json_deserialize_pspec (&value, pspec, val);
331         }
332
333       if (res)
334         {
335           JSON_NOTE (GOBJECT, "Calling set_property('%s', '%s')",
336                      pspec->name,
337                      g_type_name (G_VALUE_TYPE (&value)));
338
339           if (set_property)
340             json_serializable_set_property (serializable, pspec, &value);
341           else
342             g_object_set_property (retval, pspec->name, &value);
343         }
344       else
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));
347
348       g_value_unset (&value);
349     }
350
351   g_list_free (members);
352
353   g_object_thaw_notify (retval);
354
355   g_type_class_unref (klass);
356
357   return retval;
358 }
359
360 static JsonObject *
361 json_gobject_dump (GObject *gobject)
362 {
363   JsonSerializableIface *iface = NULL;
364   JsonSerializable *serializable = NULL;
365   gboolean list_properties = FALSE;
366   gboolean serialize_property = FALSE;
367   gboolean get_property = FALSE;
368   JsonObject *object;
369   GParamSpec **pspecs;
370   guint n_pspecs, i;
371
372   if (JSON_IS_SERIALIZABLE (gobject))
373     {
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);
379     }
380
381   object = json_object_new ();
382
383   if (list_properties)
384     pspecs = json_serializable_list_properties (serializable, &n_pspecs);
385   else
386     pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (gobject), &n_pspecs);
387
388   for (i = 0; i < n_pspecs; i++)
389     {
390       GParamSpec *pspec = pspecs[i];
391       GValue value = { 0, };
392       JsonNode *node = NULL;
393
394       /* read only what we can */
395       if (!(pspec->flags & G_PARAM_READABLE))
396         continue;
397
398       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
399
400       if (get_property)
401         json_serializable_get_property (serializable, pspec, &value);
402       else
403         g_object_get_property (gobject, pspec->name, &value);
404
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
408        */
409       if (serialize_property)
410         {
411           node = iface->serialize_property (serializable, pspec->name,
412                                             &value,
413                                             pspec);
414         }
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);
418
419       if (node)
420         json_object_set_member (object, pspec->name, node);
421
422       g_value_unset (&value);
423     }
424
425   g_free (pspecs);
426
427   return object;
428 }
429
430 gboolean
431 json_deserialize_pspec (GValue     *value,
432                         GParamSpec *pspec,
433                         JsonNode   *node)
434 {
435   GValue node_value = { 0, };
436   gboolean retval = FALSE;
437
438   if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_BOXED)
439     {
440       JsonNodeType node_type = json_node_get_node_type (node);
441       GType boxed_type = G_VALUE_TYPE (value);
442
443       if (json_boxed_can_deserialize (boxed_type, node_type))
444         {
445           gpointer boxed = json_boxed_deserialize (boxed_type, node);
446
447           g_value_take_boxed (value, boxed);
448
449           return TRUE;
450         }
451     }
452
453   switch (JSON_NODE_TYPE (node))
454     {
455     case JSON_NODE_OBJECT:
456       if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT))
457         {
458           GObject *object;
459
460           object = json_gobject_new (G_VALUE_TYPE (value), json_node_get_object (node));
461           if (object != NULL)
462             g_value_take_object (value, object);
463           else
464             g_value_set_object (value, NULL);
465
466           retval = TRUE;
467         }
468       break;
469
470     case JSON_NODE_ARRAY:
471       if (G_VALUE_HOLDS (value, G_TYPE_STRV))
472         {
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);
476
477           for (i = 0; i < array_len; i++)
478             {
479               JsonNode *val = json_array_get_element (array, i);
480
481               if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE)
482                 continue;
483
484               if (json_node_get_string (val) != NULL)
485                 g_ptr_array_add (str_array, (gpointer) json_node_get_string (val));
486             }
487
488           g_ptr_array_add (str_array, NULL);
489
490           g_value_set_boxed (value, str_array->pdata);
491
492           g_ptr_array_free (str_array, TRUE);
493
494           retval = TRUE;
495         }
496       break;
497
498     case JSON_NODE_VALUE:
499       json_node_get_value (node, &node_value);
500 #if 0
501       {
502         gchar *node_str = g_strdup_value_contents (&node_value);
503         g_debug ("%s: value type '%s' := node value type '%s' -> '%s'",
504                  G_STRLOC,
505                  g_type_name (G_VALUE_TYPE (value)),
506                  g_type_name (G_VALUE_TYPE (&node_value)),
507                  node_str);
508         g_free (node_str);
509       }
510 #endif
511
512       switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
513         {
514         case G_TYPE_BOOLEAN:
515         case G_TYPE_INT64:
516         case G_TYPE_STRING:
517           if (G_VALUE_HOLDS (&node_value, G_VALUE_TYPE (value)))
518             {
519               g_value_copy (&node_value, value);
520               retval = TRUE;
521             }
522           break;
523
524         case G_TYPE_INT:
525           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
526             {
527               g_value_set_int (value, (gint) g_value_get_int64 (&node_value));
528               retval = TRUE;
529             }
530           break;
531
532         case G_TYPE_CHAR:
533           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
534             {
535 #if GLIB_CHECK_VERSION (2, 31, 0)
536               g_value_set_schar (value, (gchar) g_value_get_int64 (&node_value));
537 #else
538               g_value_set_char (value, (gchar) g_value_get_int64 (&node_value));
539 #endif
540               retval = TRUE;
541             }
542           break;
543
544         case G_TYPE_UINT:
545           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
546             {
547               g_value_set_uint (value, (guint) g_value_get_int64 (&node_value));
548               retval = TRUE;
549             }
550           break;
551
552         case G_TYPE_UCHAR:
553           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
554             {
555               g_value_set_uchar (value, (guchar) g_value_get_int64 (&node_value));
556               retval = TRUE;
557             }
558           break;
559
560         case G_TYPE_DOUBLE:
561
562           if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
563             {
564               g_value_set_double (value, g_value_get_double (&node_value));
565               retval = TRUE;
566             }
567           else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
568             {
569               g_value_set_double (value, (gdouble) g_value_get_int64 (&node_value));
570               retval = TRUE;
571             }
572
573           break;
574
575         case G_TYPE_FLOAT:
576           if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
577             {
578               g_value_set_float (value, (gfloat) g_value_get_double (&node_value));
579               retval = TRUE;
580             }
581           else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
582             {
583               g_value_set_float (value, (gfloat) g_value_get_int64 (&node_value));
584               retval = TRUE;
585             }
586
587           break;
588
589         case G_TYPE_ENUM:
590           {
591             gint enum_value = 0;
592
593             if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
594               {
595                 enum_value = g_value_get_int64 (&node_value);
596                 retval = TRUE;
597               }
598             else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
599               {
600                 retval = enum_from_string (G_VALUE_TYPE (value),
601                                            g_value_get_string (&node_value),
602                                            &enum_value);
603               }
604
605             if (retval)
606               g_value_set_enum (value, enum_value);
607           }
608           break;
609
610         case G_TYPE_FLAGS:
611           {
612             gint flags_value = 0;
613
614             if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
615               {
616                 flags_value = g_value_get_int64 (&node_value);
617                 retval = TRUE;
618               }
619             else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
620               {
621                 retval = flags_from_string (G_VALUE_TYPE (value),
622                                             g_value_get_string (&node_value),
623                                             &flags_value);
624               }
625
626             if (retval)
627               g_value_set_flags (value, flags_value);
628           }
629           break;
630
631         default:
632           retval = FALSE;
633           break;
634         }
635
636       g_value_unset (&node_value);
637       break;
638
639     case JSON_NODE_NULL:
640       if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING)
641         {
642           g_value_set_string (value, NULL);
643           retval = TRUE;
644         }
645       else if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_OBJECT)
646         {
647           g_value_set_object (value, NULL);
648           retval = TRUE;
649         }
650       else
651         retval = FALSE;
652
653       break;
654     }
655
656   return retval;
657 }
658
659 JsonNode *
660 json_serialize_pspec (const GValue *real_value,
661                       GParamSpec   *pspec)
662 {
663   JsonNode *retval = NULL;
664   GValue value = { 0, };
665   JsonNodeType node_type;
666
667   switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (real_value)))
668     {
669     case G_TYPE_INT64:
670     case G_TYPE_BOOLEAN:
671     case G_TYPE_DOUBLE:
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);
678       break;
679
680     case G_TYPE_STRING:
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);
684       else
685         {
686           retval = json_node_new (JSON_NODE_VALUE);
687           json_node_set_string (retval, g_value_get_string (real_value));
688           break;
689         }
690       break;
691
692     case G_TYPE_INT:
693       retval = json_node_new (JSON_NODE_VALUE);
694       json_node_set_int (retval, g_value_get_int (real_value));
695       break;
696
697     case G_TYPE_FLOAT:
698       retval = json_node_new (JSON_NODE_VALUE);
699       json_node_set_double (retval, g_value_get_float (real_value));
700       break;
701
702     case G_TYPE_BOXED:
703       if (G_VALUE_HOLDS (real_value, G_TYPE_STRV))
704         {
705           gchar **strv = g_value_get_boxed (real_value);
706           gint i, strv_len;
707           JsonArray *array;
708
709           strv_len = g_strv_length (strv);
710           array = json_array_sized_new (strv_len);
711
712           for (i = 0; i < strv_len; i++)
713             {
714               JsonNode *str = json_node_new (JSON_NODE_VALUE);
715
716               json_node_set_string (str, strv[i]);
717               json_array_add_element (array, str);
718             }
719
720           retval = json_node_new (JSON_NODE_ARRAY);
721           json_node_take_array (retval, array);
722         }
723       else if (json_boxed_can_serialize (G_VALUE_TYPE (real_value), &node_type))
724         {
725           gpointer boxed = g_value_get_boxed (real_value);
726
727           retval = json_boxed_serialize (G_VALUE_TYPE (real_value), boxed);
728         }
729       else
730         g_warning ("Boxed type '%s' is not handled by JSON-GLib",
731                    g_type_name (G_VALUE_TYPE (real_value)));
732       break;
733
734     case G_TYPE_UINT:
735       retval = json_node_new (JSON_NODE_VALUE);
736       json_node_set_int (retval, g_value_get_uint (real_value));
737       break;
738
739     case G_TYPE_LONG:
740       retval = json_node_new (JSON_NODE_VALUE);
741       json_node_set_int (retval, g_value_get_long (real_value));
742       break;
743
744     case G_TYPE_ULONG:
745       retval = json_node_new (JSON_NODE_VALUE);
746       json_node_set_int (retval, g_value_get_long (real_value));
747       break;
748
749     case G_TYPE_CHAR:
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));
753 #else
754       json_node_set_int (retval, g_value_get_char (real_value));
755 #endif
756       break;
757
758     case G_TYPE_UCHAR:
759       retval = json_node_new (JSON_NODE_VALUE);
760       json_node_set_int (retval, g_value_get_uchar (real_value));
761       break;
762
763     case G_TYPE_ENUM:
764       retval = json_node_new (JSON_NODE_VALUE);
765       json_node_set_int (retval, g_value_get_enum (real_value));
766       break;
767
768     case G_TYPE_FLAGS:
769       retval = json_node_new (JSON_NODE_VALUE);
770       json_node_set_int (retval, g_value_get_flags (real_value));
771       break;
772
773     case G_TYPE_OBJECT:
774       {
775         GObject *object = g_value_get_object (real_value);
776
777         if (object != NULL)
778           {
779             retval = json_node_new (JSON_NODE_OBJECT);
780             json_node_take_object (retval, json_gobject_dump (object));
781           }
782         else
783           retval = json_node_new (JSON_NODE_NULL);
784       }
785       break;
786
787     case G_TYPE_NONE:
788       retval = json_node_new (JSON_NODE_NULL);
789       break;
790
791     default:
792       g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
793       break;
794     }
795
796   return retval;
797 }
798
799 /**
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
804  *
805  * Creates a new #GObject of type @gtype, and constructs it
806  * using the members of the passed #JsonObject
807  *
808  * Return value: (transfer full): The newly created #GObject
809  *   instance. Use g_object_unref() to free the resources
810  *   allocated by this function
811  *
812  * Since: 0.10
813  */
814 GObject *
815 json_gobject_deserialize (GType     gtype,
816                           JsonNode *node)
817 {
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);
820
821   return json_gobject_new (gtype, json_node_get_object (node));
822 }
823
824 /**
825  * json_gobject_serialize:
826  * @gobject: a #GObject
827  *
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
831  *
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
835  *
836  * Since: 0.10
837  */
838 JsonNode *
839 json_gobject_serialize (GObject *gobject)
840 {
841   JsonNode *retval;
842
843   g_return_val_if_fail (G_IS_OBJECT (gobject), NULL);
844
845   retval = json_node_new (JSON_NODE_OBJECT);
846   json_node_take_object (retval, json_gobject_dump (gobject));
847
848   return retval;
849 }
850
851 /**
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
857  *
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.
863  *
864  * Note: the JSON data stream must be an object declaration.
865  *
866  * Return value: (transfer full): a #GObject or %NULL
867  *
868  * Since: 0.4
869  *
870  * Deprecated: 0.10: Use json_gobject_from_data() instead
871  */
872 GObject *
873 json_construct_gobject (GType         gtype,
874                         const gchar  *data,
875                         gsize         length,
876                         GError      **error)
877 {
878   return json_gobject_from_data (gtype, data, strlen (data), error);
879 }
880
881 /**
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
887  *
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.
893  *
894  * Note: the JSON data stream must be an object declaration.
895  *
896  * Return value: (transfer full): a #GObject or %NULL
897  *
898  * Since: 0.10
899  */
900 GObject *
901 json_gobject_from_data (GType         gtype,
902                         const gchar  *data,
903                         gssize        length,
904                         GError      **error)
905 {
906   JsonParser *parser;
907   JsonNode *root;
908   GError *parse_error;
909   GObject *retval;
910
911   g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
912   g_return_val_if_fail (data != NULL, NULL);
913
914   if (length < 0)
915     length = strlen (data);
916
917   parser = json_parser_new ();
918
919   parse_error = NULL;
920   json_parser_load_from_data (parser, data, length, &parse_error);
921   if (parse_error)
922     {
923       g_propagate_error (error, parse_error);
924       g_object_unref (parser);
925       return NULL;
926     }
927
928   root = json_parser_get_root (parser);
929   if (root == NULL || JSON_NODE_TYPE (root) != JSON_NODE_OBJECT)
930     {
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);
937       return NULL;
938     }
939
940   retval = json_gobject_deserialize (gtype, root);
941
942   g_object_unref (parser);
943
944   return retval;
945 }
946
947 /**
948  * json_serialize_gobject:
949  * @gobject: a #GObject
950  * @length: (out): return value for the length of the buffer, or %NULL
951  *
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.
956  *
957  * Return value: a JSON data stream representing the passed #GObject
958  *
959  * Deprecated: 0.10: Use json_gobject_to_data() instead
960  */
961 gchar *
962 json_serialize_gobject (GObject *gobject,
963                         gsize   *length)
964 {
965   return json_gobject_to_data (gobject, length);
966 }
967
968 /**
969  * json_gobject_to_data:
970  * @gobject: a #GObject
971  * @length: (out): return value for the length of the buffer, or %NULL
972  *
973  * Serializes a #GObject into a JSON data stream, iterating recursively
974  * over each property.
975  *
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
979  * JSON native types.
980  *
981  * Return value: a JSON data stream representing the passed #GObject
982  *
983  * Since: 0.10
984  */
985 gchar *
986 json_gobject_to_data (GObject *gobject,
987                       gsize   *length)
988 {
989   JsonGenerator *gen;
990   JsonNode *root;
991   gchar *data;
992
993   g_return_val_if_fail (G_OBJECT (gobject), NULL);
994
995   root = json_gobject_serialize (gobject);
996
997   gen = g_object_new (JSON_TYPE_GENERATOR,
998                       "root", root,
999                       "pretty", TRUE,
1000                       "indent", 2,
1001                       NULL);
1002
1003   data = json_generator_to_data (gen, length);
1004   g_object_unref (gen);
1005
1006   json_node_free (root);
1007
1008   return data;
1009 }