Imported Upstream version 1.2.4
[platform/upstream/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
25  * instances 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 #include "config.h"
36
37 #include <string.h>
38 #include <stdlib.h>
39
40 #include <glib/gi18n-lib.h>
41
42 #include "json-types-private.h"
43 #include "json-gobject-private.h"
44
45 #include "json-debug.h"
46 #include "json-parser.h"
47 #include "json-generator.h"
48
49 static gboolean
50 enum_from_string (GType        type,
51                   const gchar *string,
52                   gint        *enum_value)
53 {
54   GEnumClass *eclass;
55   GEnumValue *ev;
56   gchar *endptr;
57   gint value;
58   gboolean retval = TRUE;
59
60   g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
61   g_return_val_if_fail (string != NULL, 0);
62
63   value = strtoul (string, &endptr, 0);
64   if (endptr != string) /* parsed a number */
65     *enum_value = value;
66   else
67     {
68       eclass = g_type_class_ref (type);
69       ev = g_enum_get_value_by_name (eclass, string);
70       if (!ev)
71         ev = g_enum_get_value_by_nick (eclass, string);
72
73       if (ev)
74         *enum_value = ev->value;
75       else
76         retval = FALSE;
77
78       g_type_class_unref (eclass);
79     }
80
81   return retval;
82 }
83
84 static gboolean
85 flags_from_string (GType        type,
86                    const gchar *string,
87                    gint        *flags_value)
88 {
89   GFlagsClass *fclass;
90   gchar *endptr, *prevptr;
91   guint i, j, ret, value;
92   gchar *flagstr;
93   GFlagsValue *fv;
94   const gchar *flag;
95   gunichar ch;
96   gboolean eos;
97
98   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
99   g_return_val_if_fail (string != 0, 0);
100
101   ret = TRUE;
102
103   value = strtoul (string, &endptr, 0);
104   if (endptr != string) /* parsed a number */
105     *flags_value = value;
106   else
107     {
108       fclass = g_type_class_ref (type);
109
110       flagstr = g_strdup (string);
111       for (value = i = j = 0; ; i++)
112         {
113           eos = flagstr[i] == '\0';
114
115           if (!eos && flagstr[i] != '|')
116             continue;
117
118           flag = &flagstr[j];
119           endptr = &flagstr[i];
120
121           if (!eos)
122             {
123               flagstr[i++] = '\0';
124               j = i;
125             }
126
127           /* trim spaces */
128           for (;;)
129             {
130               ch = g_utf8_get_char (flag);
131               if (!g_unichar_isspace (ch))
132                 break;
133               flag = g_utf8_next_char (flag);
134             }
135
136           while (endptr > flag)
137             {
138               prevptr = g_utf8_prev_char (endptr);
139               ch = g_utf8_get_char (prevptr);
140               if (!g_unichar_isspace (ch))
141                 break;
142               endptr = prevptr;
143             }
144
145           if (endptr > flag)
146             {
147               *endptr = '\0';
148               fv = g_flags_get_value_by_name (fclass, flag);
149
150               if (!fv)
151                 fv = g_flags_get_value_by_nick (fclass, flag);
152
153               if (fv)
154                 value |= fv->value;
155               else
156                 {
157                   ret = FALSE;
158                   break;
159                 }
160             }
161
162           if (eos)
163             {
164               *flags_value = value;
165               break;
166             }
167         }
168
169       g_free (flagstr);
170
171       g_type_class_unref (fclass);
172     }
173
174   return ret;
175 }
176
177 static GObject *
178 json_gobject_new (GType       gtype,
179                   JsonObject *object)
180 {
181   JsonSerializableIface *iface = NULL;
182   JsonSerializable *serializable = NULL;
183   gboolean find_property;
184   gboolean deserialize_property;
185   gboolean set_property;
186   GList *members, *members_left, *l;
187   guint n_members;
188   GObjectClass *klass;
189   GObject *retval;
190   GArray *construct_params;
191   gint i;
192
193   klass = g_type_class_ref (gtype);
194
195   n_members = json_object_get_size (object);
196   members = json_object_get_members (object);
197   members_left = NULL;
198
199   /* first pass: construct-only properties; here we cannot use Serializable
200    * because we don't have an instance yet; we use the default implementation
201    * of json_deserialize_pspec() to deserialize known types
202    *
203    * FIXME - find a way to allow deserialization for these properties
204    */
205   construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
206
207   for (l = members; l != NULL; l = l->next)
208     {
209       const gchar *member_name = l->data;
210       GParamSpec *pspec;
211       GParameter param = { NULL, };
212       JsonNode *val;
213       gboolean res = FALSE;
214
215       pspec = g_object_class_find_property (klass, member_name);
216       if (!pspec)
217         goto next_member;
218
219       /* we only apply construct-only properties here */
220       if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0)
221         goto next_member;
222
223       if (!(pspec->flags & G_PARAM_WRITABLE))
224         goto next_member;
225
226       g_value_init (&param.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
227
228       val = json_object_get_member (object, member_name);
229       res = json_deserialize_pspec (&param.value, pspec, val);
230       if (!res)
231         {
232           g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
233                      pspec->name, G_VALUE_TYPE_NAME (&param.value), g_type_name (gtype));
234
235           g_value_unset (&param.value);
236         }
237       else
238         {
239           param.name = g_strdup (pspec->name);
240
241           g_array_append_val (construct_params, param);
242
243           continue;
244         }
245
246     next_member:
247       members_left = g_list_prepend (members_left, l->data);
248     }
249
250   retval = g_object_newv (gtype,
251                           construct_params->len,
252                           (GParameter *) construct_params->data);
253
254   /* free the contents of the GArray */
255   for (i = 0; i < construct_params->len; i++)
256     {
257       GParameter *param = &g_array_index (construct_params, GParameter, i);
258
259       g_free ((gchar *) param->name);
260       g_value_unset (&param->value);
261     }
262
263   g_array_free (construct_params, TRUE);
264   g_list_free (members);
265
266   /* we use g_list_prepend() above, but we want to maintain
267    * the ordering of json_object_get_members() here
268    */
269   members = g_list_reverse (members_left);
270
271   /* do the Serializable type check once */
272   if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
273     {
274       serializable = JSON_SERIALIZABLE (retval);
275       iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
276       find_property = (iface->find_property != NULL);
277       deserialize_property = (iface->deserialize_property != NULL);
278       set_property = (iface->set_property != NULL);
279     }
280   else
281     {
282       find_property = FALSE;
283       deserialize_property = FALSE;
284       set_property = FALSE;
285     }
286
287   g_object_freeze_notify (retval);
288
289   for (l = members; l != NULL; l = l->next)
290     {
291       const gchar *member_name = l->data;
292       GParamSpec *pspec;
293       JsonNode *val;
294       GValue value = { 0, };
295       gboolean res = FALSE;
296
297       if (find_property)
298         pspec = json_serializable_find_property (serializable, member_name);
299       else
300         pspec = g_object_class_find_property (klass, member_name);
301
302       if (pspec == NULL)
303         continue;
304
305       /* we should have dealt with these above */
306       if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
307         continue;
308
309       if (!(pspec->flags & G_PARAM_WRITABLE))
310         continue;
311
312       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
313
314       val = json_object_get_member (object, member_name);
315
316       if (deserialize_property)
317         {
318           JSON_NOTE (GOBJECT, "Using JsonSerializable for property '%s'", pspec->name);
319           res = json_serializable_deserialize_property (serializable,
320                                                         pspec->name,
321                                                         &value,
322                                                         pspec,
323                                                         val);
324         }
325
326       if (!res)
327         {
328           JSON_NOTE (GOBJECT, "Using json_deserialize_pspec for property '%s'", pspec->name);
329           res = json_deserialize_pspec (&value, pspec, val);
330         }
331
332       if (res)
333         {
334           JSON_NOTE (GOBJECT, "Calling set_property('%s', '%s')",
335                      pspec->name,
336                      g_type_name (G_VALUE_TYPE (&value)));
337
338           if (set_property)
339             json_serializable_set_property (serializable, pspec, &value);
340           else
341             g_object_set_property (retval, pspec->name, &value);
342         }
343       else
344         g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
345                    pspec->name, g_type_name (G_VALUE_TYPE (&value)), g_type_name (gtype));
346
347       g_value_unset (&value);
348     }
349
350   g_list_free (members);
351
352   g_object_thaw_notify (retval);
353
354   g_type_class_unref (klass);
355
356   return retval;
357 }
358
359 static JsonObject *
360 json_gobject_dump (GObject *gobject)
361 {
362   JsonSerializableIface *iface = NULL;
363   JsonSerializable *serializable = NULL;
364   gboolean list_properties = FALSE;
365   gboolean serialize_property = FALSE;
366   gboolean get_property = FALSE;
367   JsonObject *object;
368   GParamSpec **pspecs;
369   guint n_pspecs, i;
370
371   if (JSON_IS_SERIALIZABLE (gobject))
372     {
373       serializable = JSON_SERIALIZABLE (gobject);
374       iface = JSON_SERIALIZABLE_GET_IFACE (gobject);
375       list_properties = (iface->list_properties != NULL);
376       serialize_property = (iface->serialize_property != NULL);
377       get_property = (iface->get_property != NULL);
378     }
379
380   object = json_object_new ();
381
382   if (list_properties)
383     pspecs = json_serializable_list_properties (serializable, &n_pspecs);
384   else
385     pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (gobject), &n_pspecs);
386
387   for (i = 0; i < n_pspecs; i++)
388     {
389       GParamSpec *pspec = pspecs[i];
390       GValue value = { 0, };
391       JsonNode *node = NULL;
392
393       /* read only what we can */
394       if (!(pspec->flags & G_PARAM_READABLE))
395         continue;
396
397       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
398
399       if (get_property)
400         json_serializable_get_property (serializable, pspec, &value);
401       else
402         g_object_get_property (gobject, pspec->name, &value);
403
404       /* if there is a serialization vfunc, then it is completely responsible
405        * for serializing the property, possibly by calling the implementation
406        * of the default JsonSerializable interface through chaining up
407        */
408       if (serialize_property)
409         {
410           node = json_serializable_serialize_property (serializable,
411                                                        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               g_value_set_schar (value, (gchar) g_value_get_int64 (&node_value));
536               retval = TRUE;
537             }
538           break;
539
540         case G_TYPE_UINT:
541           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
542             {
543               g_value_set_uint (value, (guint) g_value_get_int64 (&node_value));
544               retval = TRUE;
545             }
546           break;
547
548         case G_TYPE_UCHAR:
549           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
550             {
551               g_value_set_uchar (value, (guchar) g_value_get_int64 (&node_value));
552               retval = TRUE;
553             }
554           break;
555
556         case G_TYPE_LONG:
557           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
558             {
559               g_value_set_long (value, (glong) g_value_get_int64 (&node_value));
560               retval = TRUE;
561             }
562           break;
563
564         case G_TYPE_ULONG:
565           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
566             {
567               g_value_set_ulong (value, (gulong) g_value_get_int64 (&node_value));
568               retval = TRUE;
569             }
570           break;
571
572         case G_TYPE_UINT64:
573           if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
574             {
575               g_value_set_uint64 (value, (guint64) g_value_get_int64 (&node_value));
576               retval = TRUE;
577             }
578           break;
579
580         case G_TYPE_DOUBLE:
581
582           if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
583             {
584               g_value_set_double (value, g_value_get_double (&node_value));
585               retval = TRUE;
586             }
587           else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
588             {
589               g_value_set_double (value, (gdouble) g_value_get_int64 (&node_value));
590               retval = TRUE;
591             }
592
593           break;
594
595         case G_TYPE_FLOAT:
596           if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
597             {
598               g_value_set_float (value, (gfloat) g_value_get_double (&node_value));
599               retval = TRUE;
600             }
601           else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
602             {
603               g_value_set_float (value, (gfloat) g_value_get_int64 (&node_value));
604               retval = TRUE;
605             }
606
607           break;
608
609         case G_TYPE_ENUM:
610           {
611             gint enum_value = 0;
612
613             if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
614               {
615                 enum_value = g_value_get_int64 (&node_value);
616                 retval = TRUE;
617               }
618             else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
619               {
620                 retval = enum_from_string (G_VALUE_TYPE (value),
621                                            g_value_get_string (&node_value),
622                                            &enum_value);
623               }
624
625             if (retval)
626               g_value_set_enum (value, enum_value);
627           }
628           break;
629
630         case G_TYPE_FLAGS:
631           {
632             gint flags_value = 0;
633
634             if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
635               {
636                 flags_value = g_value_get_int64 (&node_value);
637                 retval = TRUE;
638               }
639             else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
640               {
641                 retval = flags_from_string (G_VALUE_TYPE (value),
642                                             g_value_get_string (&node_value),
643                                             &flags_value);
644               }
645
646             if (retval)
647               g_value_set_flags (value, flags_value);
648           }
649           break;
650
651         default:
652           retval = FALSE;
653           break;
654         }
655
656       g_value_unset (&node_value);
657       break;
658
659     case JSON_NODE_NULL:
660       if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING)
661         {
662           g_value_set_string (value, NULL);
663           retval = TRUE;
664         }
665       else if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_OBJECT)
666         {
667           g_value_set_object (value, NULL);
668           retval = TRUE;
669         }
670       else
671         retval = FALSE;
672
673       break;
674     }
675
676   return retval;
677 }
678
679 JsonNode *
680 json_serialize_pspec (const GValue *real_value,
681                       GParamSpec   *pspec)
682 {
683   JsonNode *retval = NULL;
684   JsonNodeType node_type;
685
686   switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (real_value)))
687     {
688     /* JSON native types */
689     case G_TYPE_INT64:
690       retval = json_node_init_int (json_node_alloc (), g_value_get_int64 (real_value));
691       break;
692
693     case G_TYPE_BOOLEAN:
694       retval = json_node_init_boolean (json_node_alloc (), g_value_get_boolean (real_value));
695       break;
696
697     case G_TYPE_DOUBLE:
698       retval = json_node_init_double (json_node_alloc (), g_value_get_double (real_value));
699       break;
700
701     case G_TYPE_STRING:
702       retval = json_node_init_string (json_node_alloc (), g_value_get_string (real_value));
703       break;
704
705     /* auto-promoted types */
706     case G_TYPE_INT:
707       retval = json_node_init_int (json_node_alloc (), g_value_get_int (real_value));
708       break;
709
710     case G_TYPE_UINT:
711       retval = json_node_init_int (json_node_alloc (), g_value_get_uint (real_value));
712       break;
713
714     case G_TYPE_LONG:
715       retval = json_node_init_int (json_node_alloc (), g_value_get_long (real_value));
716       break;
717
718     case G_TYPE_ULONG:
719       retval = json_node_init_int (json_node_alloc (), g_value_get_ulong (real_value));
720       break;
721
722     case G_TYPE_UINT64:
723       retval = json_node_init_int (json_node_alloc (), g_value_get_uint64 (real_value));
724       break;
725
726     case G_TYPE_FLOAT:
727       retval = json_node_init_double (json_node_alloc (), g_value_get_float (real_value));
728       break;
729
730     case G_TYPE_CHAR:
731       retval = json_node_alloc ();
732       json_node_init_int (retval, g_value_get_schar (real_value));
733       break;
734
735     case G_TYPE_UCHAR:
736       retval = json_node_init_int (json_node_alloc (), g_value_get_uchar (real_value));
737       break;
738
739     case G_TYPE_ENUM:
740       retval = json_node_init_int (json_node_alloc (), g_value_get_enum (real_value));
741       break;
742
743     case G_TYPE_FLAGS:
744       retval = json_node_init_int (json_node_alloc (), g_value_get_flags (real_value));
745       break;
746
747     /* complex types */
748     case G_TYPE_BOXED:
749       if (G_VALUE_HOLDS (real_value, G_TYPE_STRV))
750         {
751           gchar **strv = g_value_get_boxed (real_value);
752           gint i, strv_len;
753           JsonArray *array;
754
755           strv_len = g_strv_length (strv);
756           array = json_array_sized_new (strv_len);
757
758           for (i = 0; i < strv_len; i++)
759             {
760               JsonNode *str = json_node_new (JSON_NODE_VALUE);
761
762               json_node_set_string (str, strv[i]);
763               json_array_add_element (array, str);
764             }
765
766           retval = json_node_init_array (json_node_alloc (), array);
767           json_array_unref (array);
768         }
769       else if (json_boxed_can_serialize (G_VALUE_TYPE (real_value), &node_type))
770         {
771           gpointer boxed = g_value_get_boxed (real_value);
772
773           retval = json_boxed_serialize (G_VALUE_TYPE (real_value), boxed);
774         }
775       else
776         g_warning ("Boxed type '%s' is not handled by JSON-GLib",
777                    g_type_name (G_VALUE_TYPE (real_value)));
778       break;
779
780     case G_TYPE_OBJECT:
781       {
782         GObject *object = g_value_get_object (real_value);
783
784         retval = json_node_alloc ();
785
786         if (object != NULL)
787           {
788             json_node_init (retval, JSON_NODE_OBJECT);
789             json_node_take_object (retval, json_gobject_dump (object));
790           }
791         else
792           json_node_init_null (retval);
793       }
794       break;
795
796     case G_TYPE_NONE:
797       retval = json_node_new (JSON_NODE_NULL);
798       break;
799
800     default:
801       g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
802       break;
803     }
804
805   return retval;
806 }
807
808 /**
809  * json_gobject_deserialize:
810  * @gtype: the type of the #GObject to create
811  * @node: a #JsonNode of type %JSON_NODE_OBJECT describing the
812  *   instance of type @gtype
813  *
814  * Creates a new #GObject of type @gtype, and constructs it
815  * using the members of the passed #JsonObject
816  *
817  * Return value: (transfer full): The newly created #GObject
818  *   instance. Use g_object_unref() to free the resources
819  *   allocated by this function
820  *
821  * Since: 0.10
822  */
823 GObject *
824 json_gobject_deserialize (GType     gtype,
825                           JsonNode *node)
826 {
827   g_return_val_if_fail (g_type_is_a (gtype, G_TYPE_OBJECT), NULL);
828   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
829
830   return json_gobject_new (gtype, json_node_get_object (node));
831 }
832
833 /**
834  * json_gobject_serialize:
835  * @gobject: a #GObject
836  *
837  * Creates a #JsonNode representing the passed #GObject
838  * instance. Each member of the returned JSON object will
839  * map to a property of the #GObject
840  *
841  * Return value: (transfer full): the newly created #JsonNode
842  *   of type %JSON_NODE_OBJECT. Use json_node_unref() to free
843  *   the resources allocated by this function
844  *
845  * Since: 0.10
846  */
847 JsonNode *
848 json_gobject_serialize (GObject *gobject)
849 {
850   JsonNode *retval;
851
852   g_return_val_if_fail (G_IS_OBJECT (gobject), NULL);
853
854   retval = json_node_new (JSON_NODE_OBJECT);
855   json_node_take_object (retval, json_gobject_dump (gobject));
856
857   return retval;
858 }
859
860 /**
861  * json_construct_gobject:
862  * @gtype: the #GType of object to construct
863  * @data: a JSON data stream
864  * @length: length of the data stream
865  * @error: return location for a #GError, or %NULL
866  *
867  * Deserializes a JSON data stream and creates the corresponding
868  * #GObject class. If @gtype implements the #JsonSerializableIface
869  * interface, it will be asked to deserialize all the JSON members
870  * into the respective properties; otherwise, the default implementation
871  * will be used to translate the compatible JSON native types.
872  *
873  * Note: the JSON data stream must be an object declaration.
874  *
875  * Return value: (transfer full): a #GObject or %NULL
876  *
877  * Since: 0.4
878  *
879  * Deprecated: 0.10: Use json_gobject_from_data() instead
880  */
881 GObject *
882 json_construct_gobject (GType         gtype,
883                         const gchar  *data,
884                         gsize         length,
885                         GError      **error)
886 {
887   return json_gobject_from_data (gtype, data, strlen (data), error);
888 }
889
890 /**
891  * json_gobject_from_data:
892  * @gtype: the #GType of object to construct
893  * @data: a JSON data stream
894  * @length: length of the data stream, or -1 if it is NUL-terminated
895  * @error: return location for a #GError, or %NULL
896  *
897  * Deserializes a JSON data stream and creates the corresponding
898  * #GObject class. If @gtype implements the #JsonSerializableIface
899  * interface, it will be asked to deserialize all the JSON members
900  * into the respective properties; otherwise, the default implementation
901  * will be used to translate the compatible JSON native types.
902  *
903  * Note: the JSON data stream must be an object declaration.
904  *
905  * Return value: (transfer full): a #GObject or %NULL
906  *
907  * Since: 0.10
908  */
909 GObject *
910 json_gobject_from_data (GType         gtype,
911                         const gchar  *data,
912                         gssize        length,
913                         GError      **error)
914 {
915   JsonParser *parser;
916   JsonNode *root;
917   GError *parse_error;
918   GObject *retval;
919
920   g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
921   g_return_val_if_fail (data != NULL, NULL);
922
923   if (length < 0)
924     length = strlen (data);
925
926   parser = json_parser_new ();
927
928   parse_error = NULL;
929   json_parser_load_from_data (parser, data, length, &parse_error);
930   if (parse_error)
931     {
932       g_propagate_error (error, parse_error);
933       g_object_unref (parser);
934       return NULL;
935     }
936
937   root = json_parser_get_root (parser);
938   if (root == NULL || JSON_NODE_TYPE (root) != JSON_NODE_OBJECT)
939     {
940       g_set_error (error, JSON_PARSER_ERROR,
941                    JSON_PARSER_ERROR_PARSE,
942                    /* translators: the %s is the name of the data structure */
943                    _("Expecting a JSON object, but the root node is of type `%s'"),
944                    json_node_type_name (root));
945       g_object_unref (parser);
946       return NULL;
947     }
948
949   retval = json_gobject_deserialize (gtype, root);
950
951   g_object_unref (parser);
952
953   return retval;
954 }
955
956 /**
957  * json_serialize_gobject:
958  * @gobject: a #GObject
959  * @length: (out): return value for the length of the buffer, or %NULL
960  *
961  * Serializes a #GObject into a JSON data stream. If @gobject implements
962  * the #JsonSerializableIface interface, it will be asked to serizalize all
963  * its properties; otherwise, the default implementation will be use to
964  * translate the compatible types into JSON native types.
965  *
966  * Return value: a JSON data stream representing the passed #GObject
967  *
968  * Deprecated: 0.10: Use json_gobject_to_data() instead
969  */
970 gchar *
971 json_serialize_gobject (GObject *gobject,
972                         gsize   *length)
973 {
974   return json_gobject_to_data (gobject, length);
975 }
976
977 /**
978  * json_gobject_to_data:
979  * @gobject: a #GObject
980  * @length: (out): return value for the length of the buffer, or %NULL
981  *
982  * Serializes a #GObject into a JSON data stream, iterating recursively
983  * over each property.
984  *
985  * If @gobject implements the #JsonSerializableIface interface, it will
986  * be asked to serialize all its properties; otherwise, the default
987  * implementation will be use to translate the compatible types into
988  * JSON native types.
989  *
990  * Return value: a JSON data stream representing the passed #GObject
991  *
992  * Since: 0.10
993  */
994 gchar *
995 json_gobject_to_data (GObject *gobject,
996                       gsize   *length)
997 {
998   JsonGenerator *gen;
999   JsonNode *root;
1000   gchar *data;
1001
1002   g_return_val_if_fail (G_OBJECT (gobject), NULL);
1003
1004   root = json_gobject_serialize (gobject);
1005
1006   gen = g_object_new (JSON_TYPE_GENERATOR,
1007                       "root", root,
1008                       "pretty", TRUE,
1009                       "indent", 2,
1010                       NULL);
1011
1012   data = json_generator_to_data (gen, length);
1013   g_object_unref (gen);
1014
1015   json_node_unref (root);
1016
1017   return data;
1018 }