[giv] Embedded json-glib in source tree.



commit e84d82bf8e2928c010e768139433f3042d7752a7
Author: Dov Grobgeld <dov grobgeld gmail com>
Date:   Sun Mar 4 00:27:57 2012 +0200

    Embedded json-glib in source tree.

 ChangeLog                                         |    4 +
 SConstruct                                        |    8 +-
 src/SConscript                                    |    2 +-
 src/glib-jsonrpc/SConscript                       |    6 +-
 src/glib-jsonrpc/json-glib/SConscript             |   22 +
 src/glib-jsonrpc/json-glib/json-array.c           |  709 ++++++++
 src/glib-jsonrpc/json-glib/json-builder.c         |  684 ++++++++
 src/glib-jsonrpc/json-glib/json-builder.h         |  106 ++
 src/glib-jsonrpc/json-glib/json-debug.c           |   39 +
 src/glib-jsonrpc/json-glib/json-debug.h           |   47 +
 src/glib-jsonrpc/json-glib/json-enum-types.c      |  117 ++
 src/glib-jsonrpc/json-glib/json-enum-types.h      |   36 +
 src/glib-jsonrpc/json-glib/json-gboxed.c          |  354 ++++
 src/glib-jsonrpc/json-glib/json-generator.c       |  870 ++++++++++
 src/glib-jsonrpc/json-glib/json-generator.h       |  107 ++
 src/glib-jsonrpc/json-glib/json-glib.h            |   46 +
 src/glib-jsonrpc/json-glib/json-gobject-private.h |   39 +
 src/glib-jsonrpc/json-glib/json-gobject.c         | 1005 +++++++++++
 src/glib-jsonrpc/json-glib/json-gobject.h         |  182 ++
 src/glib-jsonrpc/json-glib/json-gvariant.c        | 1341 +++++++++++++++
 src/glib-jsonrpc/json-glib/json-gvariant.h        |   46 +
 src/glib-jsonrpc/json-glib/json-marshal.c         |  132 ++
 src/glib-jsonrpc/json-glib/json-marshal.h         |   37 +
 src/glib-jsonrpc/json-glib/json-node.c            |  800 +++++++++
 src/glib-jsonrpc/json-glib/json-object.c          |  856 ++++++++++
 src/glib-jsonrpc/json-glib/json-parser.c          | 1434 ++++++++++++++++
 src/glib-jsonrpc/json-glib/json-parser.h          |  173 ++
 src/glib-jsonrpc/json-glib/json-path.c            | 1033 ++++++++++++
 src/glib-jsonrpc/json-glib/json-path.h            |   97 ++
 src/glib-jsonrpc/json-glib/json-reader.c          | 1069 ++++++++++++
 src/glib-jsonrpc/json-glib/json-reader.h          |  150 ++
 src/glib-jsonrpc/json-glib/json-scanner.c         | 1861 +++++++++++++++++++++
 src/glib-jsonrpc/json-glib/json-scanner.h         |  171 ++
 src/glib-jsonrpc/json-glib/json-serializable.c    |  341 ++++
 src/glib-jsonrpc/json-glib/json-types-private.h   |   66 +
 src/glib-jsonrpc/json-glib/json-types.h           |  334 ++++
 src/glib-jsonrpc/json-glib/json-version.h         |  100 ++
 37 files changed, 14420 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 3e23839..ce38d19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2012-03-04  Dov Grobgeld  <dov grobgeld gmail com>
+
+        * Added private copy of glib-jsonrpc.
+
 2012-01-31  Dov Grobgeld  <dov grobgeld gmail com>
 
         * configure.in: Bumped version to 0.1.22
diff --git a/SConstruct b/SConstruct
index 4fea9cb..c33ff11 100644
--- a/SConstruct
+++ b/SConstruct
@@ -121,12 +121,16 @@ env.Append(CPPPATH=[],
                     "#/src/plis",
                     "#/src/gtkimageviewer",
                     "#/src/glib-jsonrpc",
+                    "#/src/glib-jsonrpc/json-glib",
                     ],
            RPATH=["agg/src"],
-           LIBS=['gtkimageviewer_local', 'agg', 'glib-jsonrpc_local']
+           LIBS=['gtkimageviewer_local',
+                 'agg',
+                 'glib-jsonrpc_local',
+                 'json-glib_local']
            )
 
-env.ParseConfig("${PKGCONFIG} --cflags --libs gtk+-2.0 glib-2.0 json-glib-1.0 gio-2.0 gthread-2.0")
+env.ParseConfig("${PKGCONFIG} --cflags --libs gtk+-2.0 glib-2.0 gio-2.0 gthread-2.0")
 
 SConscript(['src/SConscript',
             'doc/SConscript',
diff --git a/src/SConscript b/src/SConscript
index 29a1113..bbd2671 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -3,7 +3,7 @@ Import('env')
 
 libpath = ["#/src","#/src/plis",'#/src'] + env['LIBPATH']
 libs = env['LIBS'] 
-cpppath = ["gtkimageviewer"] + env['CPPPATH']
+cpppath = ["gtkimageviewer"] + env['CPPPATH'] + ["glib-jsonrpc/"]
 cppdefines = ['PACKAGE_DOC_DIR=\'"${PACKAGE_DOC_DIR}"\'',
               'PACKAGE_PLUGIN_DIR=\'"${PACKAGE_PLUGIN_DIR}"\'',
               ]
diff --git a/src/glib-jsonrpc/SConscript b/src/glib-jsonrpc/SConscript
index ad65c7a..48dff41 100644
--- a/src/glib-jsonrpc/SConscript
+++ b/src/glib-jsonrpc/SConscript
@@ -3,4 +3,8 @@ Import('env')
 env.Library("glib-jsonrpc_local",
             ["glib-jsonrpc-json.c",
              "glib-jsonrpc-server.c",
-             "glib-jsonrpc-client.c"])
+             "glib-jsonrpc-client.c"],
+            CPPPATH=["."]+env['CPPPATH'])
+
+SConscript(['json-glib/SConscript'],
+           exports='env')
diff --git a/src/glib-jsonrpc/json-glib/SConscript b/src/glib-jsonrpc/json-glib/SConscript
new file mode 100644
index 0000000..8d4b94c
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/SConscript
@@ -0,0 +1,22 @@
+Import('env')
+
+env2 = env.Clone()
+env2.Library("json-glib_local",
+             ["json-array.c",
+              "json-builder.c",
+              "json-debug.c",
+              "json-enum-types.c",
+              "json-gboxed.c",
+              "json-generator.c",
+              "json-gobject.c",
+              "json-gvariant.c",
+              "json-marshal.c",
+              "json-node.c",
+              "json-object.c",
+              "json-parser.c",
+              "json-path.c",
+              "json-reader.c",
+              "json-scanner.c",
+              "json-serializable.c"],
+             CPPDEFINES=['JSON_COMPILATION'],
+             CPPPATH=['..']+env['CPPPATH'])
diff --git a/src/glib-jsonrpc/json-glib/json-array.c b/src/glib-jsonrpc/json-glib/json-array.c
new file mode 100644
index 0000000..44caf1e
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-array.c
@@ -0,0 +1,709 @@
+/* json-array.c - JSON array implementation
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "json-types-private.h"
+
+/**
+ * SECTION:json-array
+ * @short_description: a JSON array representation
+ *
+ * #JsonArray is the representation of the array type inside JSON. It contains
+ * #JsonNode<!-- -->s, which may contain fundamental types, other arrays or
+ * objects.
+ *
+ * Since arrays can be expensive, they are reference counted. You can control
+ * the lifetime of a #JsonArray using json_array_ref() and json_array_unref().
+ *
+ * To append an element, use json_array_add_element().
+ * To extract an element at a given index, use json_array_get_element().
+ * To retrieve the entire array in list form, use json_array_get_elements().
+ * To retrieve the length of the array, use json_array_get_length().
+ */
+
+G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref);
+
+/**
+ * json_array_new:
+ *
+ * Creates a new #JsonArray.
+ *
+ * Return value: the newly created #JsonArray
+ */
+JsonArray *
+json_array_new (void)
+{
+  JsonArray *array;
+
+  array = g_slice_new (JsonArray);
+
+  array->ref_count = 1;
+  array->elements = g_ptr_array_new ();
+
+  return array;
+}
+
+/**
+ * json_array_sized_new:
+ * @n_elements: number of slots to pre-allocate
+ *
+ * Creates a new #JsonArray with @n_elements slots already allocated.
+ *
+ * Return value: the newly created #JsonArray
+ */
+JsonArray *
+json_array_sized_new (guint n_elements)
+{
+  JsonArray *array;
+
+  array = g_slice_new (JsonArray);
+  
+  array->ref_count = 1;
+  array->elements = g_ptr_array_sized_new (n_elements);
+
+  return array;
+}
+
+/**
+ * json_array_ref:
+ * @array: a #JsonArray
+ *
+ * Increase by one the reference count of a #JsonArray.
+ *
+ * Return value: the passed #JsonArray, with the reference count
+ *   increased by one.
+ */
+JsonArray *
+json_array_ref (JsonArray *array)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (array->ref_count > 0, NULL);
+
+  g_atomic_int_add (&array->ref_count, 1);
+
+  return array;
+}
+
+/**
+ * json_array_unref:
+ * @array: a #JsonArray
+ *
+ * Decreases by one the reference count of a #JsonArray. If the
+ * reference count reaches zero, the array is destroyed and all
+ * its allocated resources are freed.
+ */
+void
+json_array_unref (JsonArray *array)
+{
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (array->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&array->ref_count))
+    {
+      guint i;
+
+      for (i = 0; i < array->elements->len; i++)
+        json_node_free (g_ptr_array_index (array->elements, i));
+
+      g_ptr_array_free (array->elements, TRUE);
+      array->elements = NULL;
+
+      g_slice_free (JsonArray, array);
+    }
+}
+
+/**
+ * json_array_get_elements:
+ * @array: a #JsonArray
+ *
+ * Gets the elements of a #JsonArray as a list of #JsonNode<!-- -->s.
+ *
+ * Return value: (element-type JsonNode) (transfer container): a #GList
+ *   containing the elements of the array. The contents of the list are
+ *   owned by the array and should never be modified or freed. Use
+ *   g_list_free() on the returned list when done using it
+ */
+GList *
+json_array_get_elements (JsonArray *array)
+{
+  GList *retval;
+  guint i;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  retval = NULL;
+  for (i = 0; i < array->elements->len; i++)
+    retval = g_list_prepend (retval,
+                             g_ptr_array_index (array->elements, i));
+
+  return g_list_reverse (retval);
+}
+
+/**
+ * json_array_dup_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Retrieves a copy of the #JsonNode containing the value of the
+ * element at @index_ inside a #JsonArray
+ *
+ * Return value: (transfer full): a copy of the #JsonNode at the requested
+ *   index. Use json_node_free() when done.
+ *
+ * Since: 0.6
+ */
+JsonNode *
+json_array_dup_element (JsonArray *array,
+                        guint      index_)
+{
+  JsonNode *retval;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  retval = json_array_get_element (array, index_);
+  if (!retval)
+    return NULL;
+
+  return json_node_copy (retval);
+}
+
+/**
+ * json_array_get_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ * 
+ * Retrieves the #JsonNode containing the value of the element at @index_
+ * inside a #JsonArray.
+ *
+ * Return value: (transfer none): a pointer to the #JsonNode at the requested index
+ */
+JsonNode *
+json_array_get_element (JsonArray *array,
+                        guint      index_)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  return g_ptr_array_index (array->elements, index_);
+}
+
+/**
+ * json_array_get_int_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the integer value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_int()
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gint64
+json_array_get_int_element (JsonArray *array,
+                            guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, 0);
+  g_return_val_if_fail (index_ < array->elements->len, 0);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, 0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+  return json_node_get_int (node);
+}
+
+/**
+ * json_array_get_double_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the floating point value of the element at
+ * @index_ inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_double()
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.8
+ */
+gdouble
+json_array_get_double_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, 0.0);
+  g_return_val_if_fail (index_ < array->elements->len, 0.0);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, 0.0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+  return json_node_get_double (node);
+}
+
+/**
+ * json_array_get_boolean_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the boolean value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_boolean()
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_boolean_element (JsonArray *array,
+                                guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, FALSE);
+  g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, FALSE);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+  return json_node_get_boolean (node);
+}
+
+/**
+ * json_array_get_string_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the string value of the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_string()
+ *
+ * Return value: the string value; the returned string is owned by
+ *   the #JsonArray and should not be modified or freed
+ *
+ * Since: 0.8
+ */
+const gchar *
+json_array_get_string_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_string (node);
+}
+
+/**
+ * json_array_get_null_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves whether the element at @index_ is set to null
+ *
+ * See also: json_array_get_element(), JSON_NODE_TYPE(), %JSON_NODE_NULL
+ *
+ * Return value: %TRUE if the element is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_array_get_null_element (JsonArray *array,
+                             guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, FALSE);
+  g_return_val_if_fail (index_ < array->elements->len, FALSE);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  return JSON_NODE_TYPE (node) == JSON_NODE_NULL;
+}
+
+/**
+ * json_array_get_array_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the array from the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_array()
+ *
+ * Return value: (transfer none): the array
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_array_get_array_element (JsonArray *array,
+                              guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_array (node);
+}
+
+/**
+ * json_array_get_object_element:
+ * @array: a #JsonArray
+ * @index_: the index of the element to retrieve
+ *
+ * Conveniently retrieves the object from the element at @index_
+ * inside @array
+ *
+ * See also: json_array_get_element(), json_node_get_object()
+ *
+ * Return value: (transfer none): the object
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_array_get_object_element (JsonArray *array,
+                               guint      index_)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (index_ < array->elements->len, NULL);
+
+  node = g_ptr_array_index (array->elements, index_);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_object (node);
+}
+
+/**
+ * json_array_get_length:
+ * @array: a #JsonArray
+ *
+ * Retrieves the length of a #JsonArray
+ *
+ * Return value: the length of the array
+ */
+guint
+json_array_get_length (JsonArray *array)
+{
+  g_return_val_if_fail (array != NULL, 0);
+
+  return array->elements->len;
+}
+
+/**
+ * json_array_add_element:
+ * @array: a #JsonArray
+ * @node: (transfer full): a #JsonNode
+ *
+ * Appends @node inside @array. The array will take ownership of the
+ * #JsonNode.
+ */
+void
+json_array_add_element (JsonArray *array,
+                        JsonNode  *node)
+{
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (node != NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_int_element:
+ * @array: a #JsonArray
+ * @value: an integer value
+ *
+ * Conveniently adds an integer @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_int()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_int_element (JsonArray *array,
+                            gint64     value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_int (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_double_element:
+ * @array: a #JsonArray
+ * @value: a floating point value
+ *
+ * Conveniently adds a floating point @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_double()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_double_element (JsonArray *array,
+                               gdouble    value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_double (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_boolean_element:
+ * @array: a #JsonArray
+ * @value: a boolean value
+ *
+ * Conveniently adds a boolean @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_boolean()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_boolean_element (JsonArray *array,
+                                gboolean   value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_boolean (node, value);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_string_element:
+ * @array: a #JsonArray
+ * @value: a string value
+ *
+ * Conveniently adds a string @value into @array
+ *
+ * See also: json_array_add_element(), json_node_set_string()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_string_element (JsonArray   *array,
+                               const gchar *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_VALUE);
+      json_node_set_string (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_null_element:
+ * @array: a #JsonArray
+ *
+ * Conveniently adds a null element into @array
+ *
+ * See also: json_array_add_element(), %JSON_NODE_NULL
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_null_element (JsonArray *array)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+
+  node = json_node_new (JSON_NODE_NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_array_element:
+ * @array: a #JsonArray
+ * @value: (transfer full): a #JsonArray
+ *
+ * Conveniently adds an array into @array. The @array takes ownership
+ * of the newly added #JsonArray
+ *
+ * See also: json_array_add_element(), json_node_take_array()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_array_element (JsonArray *array,
+                              JsonArray *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_ARRAY);
+      json_node_take_array (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_add_object_element:
+ * @array: a #JsonArray
+ * @value: (transfer full): a #JsonObject
+ *
+ * Conveniently adds an object into @array. The @array takes ownership
+ * of the newly added #JsonObject
+ *
+ * See also: json_array_add_element(), json_node_take_object()
+ *
+ * Since: 0.8
+ */
+void
+json_array_add_object_element (JsonArray  *array,
+                               JsonObject *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (value != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_OBJECT);
+      json_node_take_object (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  g_ptr_array_add (array->elements, node);
+}
+
+/**
+ * json_array_remove_element:
+ * @array: a #JsonArray
+ * @index_: the position of the element to be removed
+ *
+ * Removes the #JsonNode inside @array at @index_ freeing its allocated
+ * resources.
+ */
+void
+json_array_remove_element (JsonArray *array,
+                           guint      index_)
+{
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (index_ < array->elements->len);
+
+  json_node_free (g_ptr_array_remove_index (array->elements, index_));
+}
+
+/**
+ * json_array_foreach_element:
+ * @array: a #JsonArray
+ * @func: (scope call): the function to be called on each element
+ * @data: (closure): data to be passed to the function
+ *
+ * Iterates over all elements of @array and calls @func on
+ * each one of them.
+ *
+ * It is safe to change the value of a #JsonNode of the @array
+ * from within the iterator @func, but it is not safe to add or
+ * remove elements from the @array.
+ *
+ * Since: 0.8
+ */
+void
+json_array_foreach_element (JsonArray        *array,
+                            JsonArrayForeach  func,
+                            gpointer          data)
+{
+  gint i;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (func != NULL);
+
+  for (i = 0; i < array->elements->len; i++)
+    {
+      JsonNode *element_node;
+
+      element_node = g_ptr_array_index (array->elements, i);
+
+      (* func) (array, i, element_node, data);
+    }
+}
diff --git a/src/glib-jsonrpc/json-glib/json-builder.c b/src/glib-jsonrpc/json-glib/json-builder.c
new file mode 100644
index 0000000..9fa6859
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-builder.c
@@ -0,0 +1,684 @@
+/* json-generator.c - JSON tree builder
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010  Luca Bruno <lethalman88 gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Luca Bruno  <lethalman88 gmail com>
+ */
+
+/**
+ * SECTION:json-builder
+ * @Title: JsonBuilder
+ * @short_description: Generates JSON trees
+ * @See_Also: JsonGenerator
+ *
+ * #JsonBuilder provides an object for generating a JSON tree.
+ * You can generate only one tree with one #JsonBuilder instance.
+ *
+ * The root of the JSON tree can be either a #JsonObject or a #JsonArray.
+ * Thus the first call must necessarily be either
+ * json_builder_begin_object() or json_builder_begin_array().
+ *
+ * For convenience to language bindings, #JsonBuilder returns itself from
+ * most of functions, making it easy to chain function calls.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "json-types-private.h"
+
+#include "json-builder.h"
+
+#define JSON_BUILDER_GET_PRIVATE(obj) \
+        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_BUILDER, JsonBuilderPrivate))
+
+struct _JsonBuilderPrivate
+{
+  GQueue *stack;
+  JsonNode *root;
+};
+
+typedef enum
+{
+  JSON_BUILDER_MODE_OBJECT,
+  JSON_BUILDER_MODE_ARRAY,
+  JSON_BUILDER_MODE_MEMBER
+} JsonBuilderMode;
+
+typedef struct
+{
+  JsonBuilderMode mode;
+
+  union
+  {
+    JsonObject *object;
+    JsonArray *array;
+  } data;
+  gchar *member_name;
+} JsonBuilderState;
+
+static void
+json_builder_state_free (JsonBuilderState *state)
+{
+  if (G_LIKELY (state))
+    {
+      switch (state->mode)
+        {
+        case JSON_BUILDER_MODE_OBJECT:
+        case JSON_BUILDER_MODE_MEMBER:
+          json_object_unref (state->data.object);
+          g_free (state->member_name);
+          state->data.object = NULL;
+          state->member_name = NULL;
+          break;
+        case JSON_BUILDER_MODE_ARRAY:
+          json_array_unref (state->data.array);
+          state->data.array = NULL;
+          break;
+        default:
+          g_assert_not_reached ();
+        }
+
+      g_slice_free (JsonBuilderState, state);
+    }
+}
+
+G_DEFINE_TYPE (JsonBuilder, json_builder, G_TYPE_OBJECT);
+
+static void
+json_builder_free_all_state (JsonBuilder *builder)
+{
+  JsonBuilderState *state;
+
+  while (!g_queue_is_empty (builder->priv->stack))
+    {
+      state = g_queue_pop_head (builder->priv->stack);
+      json_builder_state_free (state);
+    }
+
+  if (builder->priv->root)
+    {
+      json_node_free (builder->priv->root);
+      builder->priv->root = NULL;
+    }
+}
+
+static void
+json_builder_finalize (GObject *gobject)
+{
+  JsonBuilderPrivate *priv = JSON_BUILDER_GET_PRIVATE (gobject);
+
+  json_builder_free_all_state (JSON_BUILDER (gobject));
+
+  g_queue_free (priv->stack);
+  priv->stack = NULL;
+
+  G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject);
+}
+
+static void
+json_builder_class_init (JsonBuilderClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (JsonBuilderPrivate));
+
+  gobject_class->finalize = json_builder_finalize;
+}
+
+static void
+json_builder_init (JsonBuilder *builder)
+{
+  JsonBuilderPrivate *priv;
+
+  builder->priv = priv = JSON_BUILDER_GET_PRIVATE (builder);
+
+  priv->stack = g_queue_new ();
+  priv->root = NULL;
+}
+
+static inline JsonBuilderMode
+json_builder_current_mode (JsonBuilder *builder)
+{
+  JsonBuilderState *state = g_queue_peek_head (builder->priv->stack);
+  return state->mode;
+}
+
+static inline gboolean
+json_builder_is_valid_add_mode (JsonBuilder *builder)
+{
+  JsonBuilderMode mode = json_builder_current_mode (builder);
+  return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY;
+}
+
+/**
+ * json_builder_new:
+ *
+ * Creates a new #JsonBuilder. You can use this object to generate a
+ * JSON tree and obtain the root #JsonNode<!-- -->s.
+ *
+ * Return value: the newly created #JsonBuilder instance
+ */
+JsonBuilder *
+json_builder_new (void)
+{
+  return g_object_new (JSON_TYPE_BUILDER, NULL);
+}
+
+/**
+ * json_builder_get_root:
+ * @builder: a #JsonBuilder
+ *
+ * Returns the root of the current constructed tree, if the build is complete
+ * (ie: all opened objects, object members and arrays are being closed).
+ *
+ * Return value: (transfer full): the #JsonNode, or %NULL if the build is not complete.
+ *   Free the returned value with json_node_free().
+ */
+JsonNode *
+json_builder_get_root (JsonBuilder *builder)
+{
+  JsonNode *root = NULL;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+
+  if (builder->priv->root)
+    root = json_node_copy (builder->priv->root);
+
+  return root;
+}
+
+/**
+ * json_builder_reset:
+ * @builder: a #JsonBuilder
+ *
+ * Resets the state of the @builder back to its initial state.
+ */
+void
+json_builder_reset (JsonBuilder *builder)
+{
+  g_return_if_fail (JSON_IS_BUILDER (builder));
+
+  json_builder_free_all_state (builder);
+}
+
+/**
+ * json_builder_begin_object:
+ * @builder: a #JsonBuilder
+ *
+ * Opens a subobject inside the given @builder. When done adding members to
+ * the subobject, json_builder_end_object() must be called.
+ *
+ * Can be called for first or only if the call is associated to an object member
+ * or an array element.
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_begin_object (JsonBuilder *builder)
+{
+  JsonObject *object;
+  JsonBuilderState *state;
+  JsonBuilderState *cur_state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (builder->priv->root == NULL, NULL);
+  g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+  object = json_object_new ();
+  cur_state = g_queue_peek_head (builder->priv->stack);
+  if (cur_state)
+    {
+      switch (cur_state->mode)
+        {
+        case JSON_BUILDER_MODE_ARRAY:
+          json_array_add_object_element (cur_state->data.array, json_object_ref (object));
+          break;
+
+        case JSON_BUILDER_MODE_MEMBER:
+          json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object));
+          g_free (cur_state->member_name);
+          cur_state->member_name = NULL;
+          cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+    }
+
+  state = g_slice_new (JsonBuilderState);
+  state->data.object = object;
+  state->member_name = NULL;
+  state->mode = JSON_BUILDER_MODE_OBJECT;
+  g_queue_push_head (builder->priv->stack, state);
+
+  return builder;
+}
+
+/**
+ * json_builder_end_object:
+ * @builder: a #JsonBuilder
+ *
+ * Closes the subobject inside the given @builder that was opened by the most
+ * recent call to json_builder_begin_object().
+ *
+ * Cannot be called after json_builder_set_member_name().
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_end_object (JsonBuilder *builder)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+  state = g_queue_pop_head (builder->priv->stack);
+
+  if (g_queue_is_empty (builder->priv->stack))
+    {
+      builder->priv->root = json_node_new (JSON_NODE_OBJECT);
+      json_node_take_object (builder->priv->root, json_object_ref (state->data.object));
+    }
+
+  json_builder_state_free (state);
+
+  return builder;
+}
+
+/**
+ * json_builder_begin_array:
+ * @builder: a #JsonBuilder
+ *
+ * Opens a subarray inside the given @builder. When done adding members to
+ * the subarray, json_builder_end_array() must be called.
+ *
+ * Can be called for first or only if the call is associated to an object member
+ * or an array element.
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_begin_array (JsonBuilder *builder)
+{
+  JsonArray *array;
+  JsonBuilderState *state;
+  JsonBuilderState *cur_state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (builder->priv->root == NULL, NULL);
+  g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL);
+
+  array = json_array_new ();
+  cur_state = g_queue_peek_head (builder->priv->stack);
+  if (cur_state)
+    {
+      switch (cur_state->mode)
+        {
+        case JSON_BUILDER_MODE_ARRAY:
+          json_array_add_array_element (cur_state->data.array, json_array_ref (array));
+          break;
+
+        case JSON_BUILDER_MODE_MEMBER:
+          json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array));
+          g_free (cur_state->member_name);
+          cur_state->member_name = NULL;
+          cur_state->mode = JSON_BUILDER_MODE_OBJECT;
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+    }
+
+  state = g_slice_new (JsonBuilderState);
+  state->data.array = array;
+  state->mode = JSON_BUILDER_MODE_ARRAY;
+  g_queue_push_head (builder->priv->stack, state);
+
+  return builder;
+}
+
+/**
+ * json_builder_end_array:
+ * @builder: a #JsonBuilder
+ *
+ * Closes the subarray inside the given @builder that was opened by the most
+ * recent call to json_builder_begin_array().
+ *
+ * Cannot be called after json_builder_set_member_name().
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_end_array (JsonBuilder *builder)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL);
+
+  state = g_queue_pop_head (builder->priv->stack);
+
+  if (g_queue_is_empty (builder->priv->stack))
+    {
+      builder->priv->root = json_node_new (JSON_NODE_ARRAY);
+      json_node_take_array (builder->priv->root, json_array_ref (state->data.array));
+    }
+
+  json_builder_state_free (state);
+
+  return builder;
+}
+
+/**
+ * json_builder_set_member_name:
+ * @builder: a #JsonBuilder
+ * @member_name: the name of the member
+ *
+ * Set the name of the next member in an object. The next call must add a value,
+ * open an object or an array.
+ *
+ * Can be called only if the call is associated to an object.
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_set_member_name (JsonBuilder *builder, const gchar *member_name)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+  state->member_name = g_strdup (member_name);
+  state->mode = JSON_BUILDER_MODE_MEMBER;
+
+  return builder;
+}
+
+/**
+ * json_builder_add_value:
+ * @builder: a #JsonBuilder
+ * @node: the value of the member or element
+ *
+ * If called after json_builder_set_member_name(), sets @node as member of the
+ * most recent opened object, otherwise @node is added as element of the most
+ * recent opened array.
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_value (JsonBuilder *builder, JsonNode *node)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_member (state->data.object, state->member_name, node);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_element (state->data.array, node);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
+
+/**
+ * json_builder_add_int_value:
+ * @builder: a #JsonBuilder
+ * @value: the value of the member or element
+ *
+ * If called after json_builder_set_member_name(), sets @value as member of the
+ * most recent opened object, otherwise @value is added as element of the most
+ * recent opened array.
+ *
+ * See also: json_builder_add_value()
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_int_value (JsonBuilder *builder, gint64 value)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_int_member (state->data.object, state->member_name, value);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_int_element (state->data.array, value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
+
+/**
+ * json_builder_add_double_value:
+ * @builder: a #JsonBuilder
+ * @value: the value of the member or element
+ *
+ * If called after json_builder_set_member_name(), sets @value as member of the
+ * most recent opened object, otherwise @value is added as element of the most
+ * recent opened array.
+ *
+ * See also: json_builder_add_value()
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_double_value (JsonBuilder *builder, gdouble value)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_double_member (state->data.object, state->member_name, value);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_double_element (state->data.array, value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
+
+/**
+ * json_builder_add_boolean_value:
+ * @builder: a #JsonBuilder
+ * @value: the value of the member or element
+ *
+ * If called after json_builder_set_member_name(), sets @value as member of the
+ * most recent opened object, otherwise @value is added as element of the most
+ * recent opened array.
+ *
+ * See also: json_builder_add_value()
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_boolean_value (JsonBuilder *builder, gboolean value)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_boolean_member (state->data.object, state->member_name, value);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_boolean_element (state->data.array, value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
+
+/**
+ * json_builder_add_string_value:
+ * @builder: a #JsonBuilder
+ * @value: the value of the member or element
+ *
+ * If called after json_builder_set_member_name(), sets @value as member of the
+ * most recent opened object, otherwise @value is added as element of the most
+ * recent opened array.
+ *
+ * See also: json_builder_add_value()
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_string_value (JsonBuilder *builder, const gchar *value)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_string_member (state->data.object, state->member_name, value);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_string_element (state->data.array, value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
+
+/**
+ * json_builder_add_null_value:
+ * @builder: a #JsonBuilder
+ *
+ * If called after json_builder_set_member_name(), sets null as member of the
+ * most recent opened object, otherwise null is added as element of the most
+ * recent opened array.
+ *
+ * See also: json_builder_add_value()
+ *
+ * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent
+ */
+JsonBuilder *
+json_builder_add_null_value (JsonBuilder *builder)
+{
+  JsonBuilderState *state;
+
+  g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL);
+  g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL);
+
+  state = g_queue_peek_head (builder->priv->stack);
+
+  switch (state->mode)
+    {
+    case JSON_BUILDER_MODE_MEMBER:
+      json_object_set_null_member (state->data.object, state->member_name);
+      g_free (state->member_name);
+      state->member_name = NULL;
+      state->mode = JSON_BUILDER_MODE_OBJECT;
+      break;
+
+    case JSON_BUILDER_MODE_ARRAY:
+      json_array_add_null_element (state->data.array);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return builder;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-builder.h b/src/glib-jsonrpc/json-glib/json-builder.h
new file mode 100644
index 0000000..e034193
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-builder.h
@@ -0,0 +1,106 @@
+/* json-builder.h: JSON tree builder
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010  Luca Bruno <lethalman88 gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Luca Bruno  <lethalman88 gmail com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_BUILDER_H__
+#define __JSON_BUILDER_H__
+
+#include <json-glib/json-types.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_BUILDER             (json_builder_get_type ())
+#define JSON_BUILDER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_BUILDER, JsonBuilder))
+#define JSON_IS_BUILDER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_BUILDER))
+#define JSON_BUILDER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), JSON_TYPE_BUILDER, JsonBuilderClass))
+#define JSON_IS_BUILDER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), JSON_TYPE_BUILDER))
+#define JSON_BUILDER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), JSON_TYPE_BUILDER, JsonBuilderClass))
+
+typedef struct _JsonBuilder           JsonBuilder;
+typedef struct _JsonBuilderPrivate    JsonBuilderPrivate;
+typedef struct _JsonBuilderClass      JsonBuilderClass;
+
+/**
+ * JsonBuilder:
+ *
+ * The <structname>JsonBuilder</structname> structure contains only
+ * private data and shouls be accessed using the provided API
+ *
+ * Since: 0.12
+ */
+struct _JsonBuilder
+{
+  /*< private >*/
+  GObject parent_instance;
+
+  JsonBuilderPrivate *priv;
+};
+
+/**
+ * JsonBuilderClass:
+ *
+ * The <structname>JsonBuilder</structname> structure contains only
+ * private data
+ *
+ * Since: 0.12
+ */
+struct _JsonBuilderClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  /* padding, for future expansion */
+  void (* _json_reserved1) (void);
+  void (* _json_reserved2) (void);
+};
+
+GType json_builder_get_type (void) G_GNUC_CONST;
+
+JsonBuilder *json_builder_new                (void);
+JsonNode    *json_builder_get_root           (JsonBuilder  *builder);
+void         json_builder_reset              (JsonBuilder  *builder);
+
+JsonBuilder *json_builder_begin_array        (JsonBuilder  *builder);
+JsonBuilder *json_builder_end_array          (JsonBuilder  *builder);
+JsonBuilder *json_builder_begin_object       (JsonBuilder  *builder);
+JsonBuilder *json_builder_end_object         (JsonBuilder  *builder);
+
+JsonBuilder *json_builder_set_member_name    (JsonBuilder  *builder,
+                                              const gchar  *member_name);
+JsonBuilder *json_builder_add_value          (JsonBuilder  *builder,
+                                              JsonNode     *node);
+JsonBuilder *json_builder_add_int_value      (JsonBuilder  *builder,
+                                              gint64        value);
+JsonBuilder *json_builder_add_double_value   (JsonBuilder  *builder,
+                                              gdouble       value);
+JsonBuilder *json_builder_add_boolean_value  (JsonBuilder  *builder,
+                                              gboolean      value);
+JsonBuilder *json_builder_add_string_value   (JsonBuilder  *builder,
+                                              const gchar  *value);
+JsonBuilder *json_builder_add_null_value     (JsonBuilder  *builder);
+
+G_END_DECLS
+
+#endif /* __JSON_BUILDER_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-debug.c b/src/glib-jsonrpc/json-glib/json-debug.c
new file mode 100644
index 0000000..c0dc2e9
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-debug.c
@@ -0,0 +1,39 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "json-debug.h"
+
+static unsigned int json_debug_flags     = 0;
+static gboolean     json_debug_flags_set = FALSE;
+
+#ifdef JSON_ENABLE_DEBUG
+static const GDebugKey json_debug_keys[] = {
+  { "parser", JSON_DEBUG_PARSER },
+  { "gobject", JSON_DEBUG_GOBJECT },
+  { "path", JSON_DEBUG_PATH }
+};
+#endif /* JSON_ENABLE_DEBUG */
+
+JsonDebugFlags
+_json_get_debug_flags (void)
+{
+#ifdef JSON_ENABLE_DEBUG
+  const gchar *env_str;
+
+  if (json_debug_flags_set)
+    return json_debug_flags;
+
+  env_str = g_getenv ("JSON_DEBUG");
+  if (env_str != NULL && *env_str != '\0')
+    {
+      json_debug_flags |= g_parse_debug_string (env_str,
+                                                json_debug_keys,
+                                                G_N_ELEMENTS (json_debug_keys));
+    }
+
+  json_debug_flags_set = TRUE;
+#endif /* JSON_ENABLE_DEBUG */
+
+  return json_debug_flags;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-debug.h b/src/glib-jsonrpc/json-glib/json-debug.h
new file mode 100644
index 0000000..695917f
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-debug.h
@@ -0,0 +1,47 @@
+#ifndef __JSON_DEBUG_H__
+#define __JSON_DEBUG_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  JSON_DEBUG_PARSER  = 1 << 0,
+  JSON_DEBUG_GOBJECT = 1 << 1,
+  JSON_DEBUG_PATH    = 1 << 2
+} JsonDebugFlags;
+
+#ifdef JSON_ENABLE_DEBUG
+
+# ifdef __GNUC__
+
+# define JSON_NOTE(type,x,a...)                 G_STMT_START {  \
+        if (_json_get_debug_flags () & JSON_DEBUG_##type) {     \
+          g_message ("[" #type "] " G_STRLOC ": " x, ##a);      \
+        }                                       } G_STMT_END
+
+# else
+/* Try the C99 version; unfortunately, this does not allow us to pass
+ * empty arguments to the macro, which means we have to
+ * do an intemediate printf.
+ */
+# define JSON_NOTE(type,...)                    G_STMT_START {  \
+        if (_json_get_debug_flags () & JSON_DEBUG_##type) {     \
+            gchar * _fmt = g_strdup_printf (__VA_ARGS__);       \
+            g_message ("[" #type "] " G_STRLOC ": %s",_fmt);    \
+            g_free (_fmt);                                      \
+        }                                       } G_STMT_END
+
+# endif /* __GNUC__ */
+
+#else
+
+#define JSON_NOTE(type,...)         G_STMT_START { } G_STMT_END
+
+#endif /* JSON_ENABLE_DEBUG */
+
+JsonDebugFlags _json_get_debug_flags (void);
+
+G_END_DECLS
+
+#endif /* __JSON_DEBUG_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-enum-types.c b/src/glib-jsonrpc/json-glib/json-enum-types.c
new file mode 100644
index 0000000..cd4b27d
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-enum-types.c
@@ -0,0 +1,117 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "json-enum-types.h"
+
+/* enumerations from "../json-glib/json-parser.h" */
+#include "../json-glib/json-parser.h"
+
+GType
+json_parser_error_get_type(void) {
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { JSON_PARSER_ERROR_PARSE, "JSON_PARSER_ERROR_PARSE", "parse" },
+        { JSON_PARSER_ERROR_TRAILING_COMMA, "JSON_PARSER_ERROR_TRAILING_COMMA", "trailing-comma" },
+        { JSON_PARSER_ERROR_MISSING_COMMA, "JSON_PARSER_ERROR_MISSING_COMMA", "missing-comma" },
+        { JSON_PARSER_ERROR_MISSING_COLON, "JSON_PARSER_ERROR_MISSING_COLON", "missing-colon" },
+        { JSON_PARSER_ERROR_INVALID_BAREWORD, "JSON_PARSER_ERROR_INVALID_BAREWORD", "invalid-bareword" },
+        { JSON_PARSER_ERROR_UNKNOWN, "JSON_PARSER_ERROR_UNKNOWN", "unknown" },
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id =
+        g_enum_register_static (g_intern_static_string ("JsonParserError"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+
+/* enumerations from "../json-glib/json-path.h" */
+#include "../json-glib/json-path.h"
+
+GType
+json_path_error_get_type(void) {
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { JSON_PATH_ERROR_INVALID_QUERY, "JSON_PATH_ERROR_INVALID_QUERY", "query" },
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id =
+        g_enum_register_static (g_intern_static_string ("JsonPathError"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+
+/* enumerations from "../json-glib/json-reader.h" */
+#include "../json-glib/json-reader.h"
+
+GType
+json_reader_error_get_type(void) {
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { JSON_READER_ERROR_NO_ARRAY, "JSON_READER_ERROR_NO_ARRAY", "no-array" },
+        { JSON_READER_ERROR_INVALID_INDEX, "JSON_READER_ERROR_INVALID_INDEX", "invalid-index" },
+        { JSON_READER_ERROR_NO_OBJECT, "JSON_READER_ERROR_NO_OBJECT", "no-object" },
+        { JSON_READER_ERROR_INVALID_MEMBER, "JSON_READER_ERROR_INVALID_MEMBER", "invalid-member" },
+        { JSON_READER_ERROR_INVALID_NODE, "JSON_READER_ERROR_INVALID_NODE", "invalid-node" },
+        { JSON_READER_ERROR_NO_VALUE, "JSON_READER_ERROR_NO_VALUE", "no-value" },
+        { JSON_READER_ERROR_INVALID_TYPE, "JSON_READER_ERROR_INVALID_TYPE", "invalid-type" },
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id =
+        g_enum_register_static (g_intern_static_string ("JsonReaderError"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+
+/* enumerations from "../json-glib/json-types.h" */
+#include "../json-glib/json-types.h"
+
+GType
+json_node_type_get_type(void) {
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { JSON_NODE_OBJECT, "JSON_NODE_OBJECT", "object" },
+        { JSON_NODE_ARRAY, "JSON_NODE_ARRAY", "array" },
+        { JSON_NODE_VALUE, "JSON_NODE_VALUE", "value" },
+        { JSON_NODE_NULL, "JSON_NODE_NULL", "null" },
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id =
+        g_enum_register_static (g_intern_static_string ("JsonNodeType"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+
+/* Generated data ends here */
+
diff --git a/src/glib-jsonrpc/json-glib/json-enum-types.h b/src/glib-jsonrpc/json-glib/json-enum-types.h
new file mode 100644
index 0000000..93dc672
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-enum-types.h
@@ -0,0 +1,36 @@
+
+/* Generated data (by glib-mkenums) */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_ENUM_TYPES_H__
+#define __JSON_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* enumerations from "../json-glib/json-parser.h" */
+GType json_parser_error_get_type (void) G_GNUC_CONST;
+#define JSON_TYPE_PARSER_ERROR (json_parser_error_get_type())
+
+/* enumerations from "../json-glib/json-path.h" */
+GType json_path_error_get_type (void) G_GNUC_CONST;
+#define JSON_TYPE_PATH_ERROR (json_path_error_get_type())
+
+/* enumerations from "../json-glib/json-reader.h" */
+GType json_reader_error_get_type (void) G_GNUC_CONST;
+#define JSON_TYPE_READER_ERROR (json_reader_error_get_type())
+
+/* enumerations from "../json-glib/json-types.h" */
+GType json_node_type_get_type (void) G_GNUC_CONST;
+#define JSON_TYPE_NODE_TYPE (json_node_type_get_type())
+
+G_END_DECLS
+
+#endif /* !__JSON_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
diff --git a/src/glib-jsonrpc/json-glib/json-gboxed.c b/src/glib-jsonrpc/json-glib/json-gboxed.c
new file mode 100644
index 0000000..8f21f75
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gboxed.c
@@ -0,0 +1,354 @@
+/* json-gboxed.c - JSON GBoxed integration
+ * 
+ * This file is part of JSON-GLib
+ *
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:json-gboxed
+ * @short_description: Serialize and deserialize GBoxed types
+ *
+ * GLib's #GBoxed type is a generic wrapper for arbitrary C structures.
+ *
+ * JSON-GLib allows serialization and deserialization of a #GBoxed type
+ * by registering functions mapping a #JsonNodeType to a specific
+ * #GType.
+ *
+ * When registering a #GBoxed type you should also register the
+ * corresponding transformation functions, e.g.:
+ *
+ * |[
+ *   GType
+ *   my_struct_get_type (void)
+ *   {
+ *     static GType boxed_type = 0;
+ *
+ *     if (boxed_type == 0)
+ *       {
+ *         boxed_type =
+ *           g_boxed_type_register_static (g_intern_static_string ("MyStruct"),
+ *                                         (GBoxedCopyFunc) my_struct_copy,
+ *                                         (GBoxedFreeFunc) my_struct_free);
+ *
+ *         json_boxed_register_serialize_func (boxed_type, JSON_NODE_OBJECT,
+ *                                             my_struct_serialize);
+ *         json_boxed_register_deserialize_func (boxed_type, JSON_NODE_OBJECT,
+ *                                               my_struct_deserialize);
+ *       }
+ *
+ *     return boxed_type;
+ *   }
+ * ]|
+ *
+ * The serialization function will be invoked by json_boxed_serialize():
+ * it will be passed a pointer to the C structure and it must return a
+ * #JsonNode. The deserialization function will be invoked by
+ * json_boxed_deserialize(): it will be passed a #JsonNode for the
+ * declared type and it must return a newly allocated C structure.
+ *
+ * It is possible to check whether a #GBoxed type can be deserialized
+ * from a specific #JsonNodeType, and whether a #GBoxed can be serialized
+ * and to which specific #JsonNodeType.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "json-types-private.h"
+#include "json-gobject.h"
+
+typedef struct _BoxedTransform  BoxedTransform;
+
+struct _BoxedTransform
+{
+  GType boxed_type;
+  gint node_type;
+
+  JsonBoxedSerializeFunc serialize;
+  JsonBoxedDeserializeFunc deserialize;
+};
+
+G_LOCK_DEFINE_STATIC (boxed_serialize);
+static GSList *boxed_serialize = NULL;
+
+G_LOCK_DEFINE_STATIC (boxed_deserialize);
+static GSList *boxed_deserialize = NULL;
+
+static gint
+boxed_transforms_cmp (gconstpointer a,
+                      gconstpointer b)
+{
+  const BoxedTransform *ta = a;
+  const BoxedTransform *tb = b;
+
+  return tb->boxed_type - ta->boxed_type;
+}
+
+static gint
+boxed_transforms_find (gconstpointer a,
+                       gconstpointer b)
+{
+  const BoxedTransform *haystack = a;
+  const BoxedTransform *needle = b;
+
+  if (needle->node_type != -1)
+    return (haystack->boxed_type == needle->boxed_type &&
+            haystack->node_type == needle->node_type) ? 0 : 1;
+  else
+    return (haystack->boxed_type == needle->boxed_type) ? 0 : 1;
+}
+
+static BoxedTransform *
+lookup_boxed_transform (GSList       *transforms,
+                        GType         gboxed_type,
+                        JsonNodeType  node_type)
+{
+  BoxedTransform lookup;
+  GSList *t;
+
+  lookup.boxed_type = gboxed_type;
+  lookup.node_type = node_type;
+
+  t = g_slist_find_custom (transforms, &lookup, boxed_transforms_find);
+  if (t == NULL)
+    return NULL;
+
+  return t->data;
+}
+
+/**
+ * json_boxed_register_serialize_func: (skip)
+ * @gboxed_type: a boxed type
+ * @node_type: a node type
+ * @serialize_func: serialization function for @boxed_type into
+ *   a #JsonNode of type @node_type
+ *
+ * Registers a serialization function for a #GBoxed of type @gboxed_type
+ * to a #JsonNode of type @node_type
+ *
+ * Since: 0.10
+ */
+void
+json_boxed_register_serialize_func (GType                  gboxed_type,
+                                    JsonNodeType           node_type,
+                                    JsonBoxedSerializeFunc serialize_func)
+{
+  BoxedTransform *t;
+
+  g_return_if_fail (G_TYPE_IS_BOXED (gboxed_type));
+  g_return_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE);
+
+  G_LOCK (boxed_serialize);
+
+  t = lookup_boxed_transform (boxed_serialize, gboxed_type, node_type);
+  if (t == NULL)
+    {
+      t = g_slice_new (BoxedTransform);
+
+      t->boxed_type = gboxed_type;
+      t->node_type = node_type;
+      t->serialize = serialize_func;
+
+      boxed_serialize = g_slist_insert_sorted (boxed_serialize, t,
+                                               boxed_transforms_cmp);
+    }
+  else
+    g_warning ("A serialization function for the boxed type %s into "
+               "JSON nodes of type %s already exists",
+               g_type_name (gboxed_type),
+               json_node_type_get_name (node_type));
+
+  G_UNLOCK (boxed_serialize);
+}
+
+/**
+ * json_boxed_register_deserialize_func: (skip)
+ * @gboxed_type: a boxed type
+ * @node_type: a node type
+ * @deserialize_func: deserialization function for @boxed_type from
+ *   a #JsonNode of type @node_type
+ *
+ * Registers a deserialization function for a #GBoxed of type @gboxed_type
+ * from a #JsonNode of type @node_type
+ *
+ * Since: 0.10
+ */
+void
+json_boxed_register_deserialize_func (GType                    gboxed_type,
+                                      JsonNodeType             node_type,
+                                      JsonBoxedDeserializeFunc deserialize_func)
+{
+  BoxedTransform *t;
+
+  g_return_if_fail (G_TYPE_IS_BOXED (gboxed_type));
+  g_return_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE);
+
+  G_LOCK (boxed_deserialize);
+
+  t = lookup_boxed_transform (boxed_deserialize, gboxed_type, node_type);
+  if (t == NULL)
+    {
+      t = g_slice_new (BoxedTransform);
+
+      t->boxed_type = gboxed_type;
+      t->node_type = node_type;
+      t->deserialize = deserialize_func;
+
+      boxed_deserialize = g_slist_insert_sorted (boxed_deserialize, t,
+                                                 boxed_transforms_cmp);
+    }
+  else
+    g_warning ("A deserialization function for the boxed type %s from "
+               "JSON nodes of type %s already exists",
+               g_type_name (gboxed_type),
+               json_node_type_get_name (node_type));
+
+  G_UNLOCK (boxed_deserialize);
+}
+
+/**
+ * json_boxed_can_serialize:
+ * @gboxed_type: a boxed type
+ * @node_type: (out): the #JsonNode type to which the boxed type can be
+ *   serialized into
+ *
+ * Checks whether it is possible to serialize a #GBoxed of
+ * type @gboxed_type into a #JsonNode. The type of the
+ * #JsonNode is placed inside @node_type if the function
+ * returns %TRUE and it's undefined otherwise.
+ *
+ * Return value: %TRUE if the type can be serialized,
+ *   and %FALSE otherwise.
+ *
+ * Since: 0.10
+ */
+gboolean
+json_boxed_can_serialize (GType         gboxed_type,
+                          JsonNodeType *node_type)
+{
+  BoxedTransform *t;
+
+  g_return_val_if_fail (G_TYPE_IS_BOXED (gboxed_type), FALSE);
+  g_return_val_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE, FALSE);
+
+  t = lookup_boxed_transform (boxed_serialize, gboxed_type, -1);
+  if (t != NULL)
+    {
+      if (node_type)
+        *node_type = t->node_type;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * json_boxed_can_deserialize:
+ * @gboxed_type: a boxed type
+ * @node_type: a #JsonNode type
+ *
+ * Checks whether it is possible to deserialize a #GBoxed of
+ * type @gboxed_type from a #JsonNode of type @node_type
+ *
+ * Return value: %TRUE if the type can be deserialized, %FALSE otherwise
+ *
+ * Since: 0.10
+ */
+gboolean
+json_boxed_can_deserialize (GType        gboxed_type,
+                            JsonNodeType node_type)
+{
+  BoxedTransform *t;
+
+  g_return_val_if_fail (G_TYPE_IS_BOXED (gboxed_type), FALSE);
+  g_return_val_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE, FALSE);
+
+  t = lookup_boxed_transform (boxed_deserialize, gboxed_type, node_type);
+  if (t != NULL)
+    return TRUE;
+
+  return FALSE;
+}
+
+/**
+ * json_boxed_serialize:
+ * @gboxed_type: a boxed type
+ * @boxed: a pointer to a #GBoxed of type @gboxed_type
+ *
+ * Serializes @boxed, a pointer to a #GBoxed of type @gboxed_type,
+ * into a #JsonNode
+ *
+ * Return value: (transfer full): a #JsonNode with the serialization of the
+ *   boxed type, or %NULL if serialization either failed or was not possible
+ *
+ * Since: 0.10
+ */
+JsonNode *
+json_boxed_serialize (GType         gboxed_type,
+                      gconstpointer boxed)
+{
+  BoxedTransform *t;
+
+  g_return_val_if_fail (G_TYPE_IS_BOXED (gboxed_type), NULL);
+  g_return_val_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE, NULL);
+  g_return_val_if_fail (boxed != NULL, NULL);
+
+  t = lookup_boxed_transform (boxed_serialize, gboxed_type, -1);
+  if (t != NULL && t->serialize != NULL)
+    return t->serialize (boxed);
+
+  return NULL;
+}
+
+/**
+ * json_boxed_deserialize:
+ * @gboxed_type: a boxed type
+ * @node: a #JsonNode
+ *
+ * Deserializes @node into a #GBoxed of @gboxed_type
+ *
+ * Return value: (transfer full): the newly allocated #GBoxed. Use
+ *   g_boxed_free() to release the resources allocated by this
+ *   function
+ *
+ * Since: 0.10
+ */
+gpointer
+json_boxed_deserialize (GType     gboxed_type,
+                        JsonNode *node)
+{
+  JsonNodeType node_type;
+  BoxedTransform *t;
+
+  g_return_val_if_fail (G_TYPE_IS_BOXED (gboxed_type), NULL);
+  g_return_val_if_fail (G_TYPE_IS_ABSTRACT (gboxed_type) == FALSE, NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+
+  node_type = json_node_get_node_type (node);
+
+  t = lookup_boxed_transform (boxed_deserialize, gboxed_type, node_type);
+  if (t != NULL && t->deserialize != NULL)
+    return t->deserialize (node);
+
+  return NULL;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-generator.c b/src/glib-jsonrpc/json-glib/json-generator.c
new file mode 100644
index 0000000..6a36bcf
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-generator.c
@@ -0,0 +1,870 @@
+/* json-generator.c - JSON streams generator
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:json-generator
+ * @short_description: Generates JSON data streams
+ *
+ * #JsonGenerator provides an object for generating a JSON data stream and
+ * put it into a buffer or a file.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "json-types-private.h"
+
+#include "json-marshal.h"
+#include "json-generator.h"
+
+#define JSON_GENERATOR_GET_PRIVATE(obj) \
+        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_GENERATOR, JsonGeneratorPrivate))
+
+struct _JsonGeneratorPrivate
+{
+  JsonNode *root;
+
+  guint indent;
+  gunichar indent_char;
+
+  guint pretty : 1;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_PRETTY,
+  PROP_INDENT,
+  PROP_ROOT,
+  PROP_INDENT_CHAR,
+
+  PROP_LAST
+};
+
+static gchar *dump_value  (JsonGenerator *generator,
+                           gint           level,
+                           const gchar   *name,
+                           JsonNode      *node,
+                           gsize         *length);
+static gchar *dump_array  (JsonGenerator *generator,
+                           gint           level,
+                           const gchar   *name,
+                           JsonArray     *array,
+                           gsize         *length);
+static gchar *dump_object (JsonGenerator *generator,
+                           gint           level,
+                           const gchar   *name,
+                           JsonObject    *object,
+                           gsize         *length);
+
+/* non-ASCII characters can't be escaped, otherwise UTF-8
+ * chars will break, so we just pregenerate this table of
+ * high characters and then we feed it to g_strescape()
+ */
+static const char json_exceptions[] = {
+  0x7f,  0x80,  0x81,  0x82,  0x83,  0x84,  0x85,  0x86,
+  0x87,  0x88,  0x89,  0x8a,  0x8b,  0x8c,  0x8d,  0x8e,
+  0x8f,  0x90,  0x91,  0x92,  0x93,  0x94,  0x95,  0x96,
+  0x97,  0x98,  0x99,  0x9a,  0x9b,  0x9c,  0x9d,  0x9e,
+  0x9f,  0xa0,  0xa1,  0xa2,  0xa3,  0xa4,  0xa5,  0xa6,
+  0xa7,  0xa8,  0xa9,  0xaa,  0xab,  0xac,  0xad,  0xae,
+  0xaf,  0xb0,  0xb1,  0xb2,  0xb3,  0xb4,  0xb5,  0xb6,
+  0xb7,  0xb8,  0xb9,  0xba,  0xbb,  0xbc,  0xbd,  0xbe,
+  0xbf,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,
+  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,
+  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,
+  0xd7,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,
+  0xdf,  0xe0,  0xe1,  0xe2,  0xe3,  0xe4,  0xe5,  0xe6,
+  0xe7,  0xe8,  0xe9,  0xea,  0xeb,  0xec,  0xed,  0xee,
+  0xef,  0xf0,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,  0xf6,
+  0xf7,  0xf8,  0xf9,  0xfa,  0xfb,  0xfc,  0xfd,  0xfe,
+  0xff,
+  '\0'   /* g_strescape() expects a NUL-terminated string */
+};
+
+static GParamSpec *generator_props[PROP_LAST] = { NULL, };
+
+G_DEFINE_TYPE (JsonGenerator, json_generator, G_TYPE_OBJECT);
+
+static gchar *
+json_strescape (const gchar *str)
+{
+  return g_strescape (str, json_exceptions);
+}
+
+static void
+json_generator_finalize (GObject *gobject)
+{
+  JsonGeneratorPrivate *priv = JSON_GENERATOR_GET_PRIVATE (gobject);
+
+  if (priv->root)
+    json_node_free (priv->root);
+
+  G_OBJECT_CLASS (json_generator_parent_class)->finalize (gobject);
+}
+
+static void
+json_generator_set_property (GObject      *gobject,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  JsonGenerator *generator = JSON_GENERATOR (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_PRETTY:
+      json_generator_set_pretty (generator, g_value_get_boolean (value));
+      break;
+
+    case PROP_INDENT:
+      json_generator_set_indent (generator, g_value_get_uint (value));
+      break;
+
+    case PROP_INDENT_CHAR:
+      json_generator_set_indent_char (generator, g_value_get_uint (value));
+      break;
+
+    case PROP_ROOT:
+      json_generator_set_root (generator, g_value_get_boxed (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+json_generator_get_property (GObject    *gobject,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  JsonGeneratorPrivate *priv = JSON_GENERATOR (gobject)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_PRETTY:
+      g_value_set_boolean (value, priv->pretty);
+      break;
+    case PROP_INDENT:
+      g_value_set_uint (value, priv->indent);
+      break;
+    case PROP_INDENT_CHAR:
+      g_value_set_uint (value, priv->indent_char);
+      break;
+    case PROP_ROOT:
+      g_value_set_boxed (value, priv->root);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+json_generator_class_init (JsonGeneratorClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (JsonGeneratorPrivate));
+
+  /**
+   * JsonGenerator:pretty:
+   *
+   * Whether the output should be "pretty-printed", with indentation and
+   * newlines. The indentation level can be controlled by using the
+   * JsonGenerator:indent property
+   */
+  generator_props[PROP_PRETTY] =
+    g_param_spec_boolean ("pretty",
+                          "Pretty",
+                          "Pretty-print the output",
+                          FALSE,
+                          G_PARAM_READWRITE);
+
+  /**
+   * JsonGenerator:indent:
+   *
+   * Number of spaces to be used to indent when pretty printing.
+   */
+  generator_props[PROP_INDENT] =
+    g_param_spec_uint ("indent",
+                       "Indent",
+                       "Number of indentation spaces",
+                       0, G_MAXUINT,
+                       2,
+                       G_PARAM_READWRITE);
+
+  /**
+   * JsonGenerator:root:
+   *
+   * The root #JsonNode to be used when constructing a JSON data
+   * stream.
+   *
+   * Since: 0.4
+   */
+  generator_props[PROP_ROOT] =
+    g_param_spec_boxed ("root",
+                        "Root",
+                        "Root of the JSON data tree",
+                        JSON_TYPE_NODE,
+                        G_PARAM_READWRITE);
+
+  /**
+   * JsonGenerator:indent-char:
+   *
+   * The character that should be used when indenting in pretty print.
+   *
+   * Since: 0.6
+   */
+  generator_props[PROP_INDENT_CHAR] =
+    g_param_spec_unichar ("indent-char",
+                          "Indent Char",
+                          "Character that should be used when indenting",
+                          ' ',
+                          G_PARAM_READWRITE);
+
+  gobject_class->set_property = json_generator_set_property;
+  gobject_class->get_property = json_generator_get_property;
+  gobject_class->finalize = json_generator_finalize;
+  g_object_class_install_properties (gobject_class, PROP_LAST, generator_props);
+}
+
+static void
+json_generator_init (JsonGenerator *generator)
+{
+  JsonGeneratorPrivate *priv;
+
+  generator->priv = priv = JSON_GENERATOR_GET_PRIVATE (generator);
+
+  priv->pretty = FALSE;
+  priv->indent = 2;
+  priv->indent_char = ' ';
+}
+
+static gchar *
+dump_value (JsonGenerator *generator,
+            gint           level,
+            const gchar   *name,
+            JsonNode      *node,
+            gsize         *length)
+{
+  JsonGeneratorPrivate *priv = generator->priv;
+  gboolean pretty = priv->pretty;
+  guint indent = priv->indent;
+  GValue value = { 0, };
+  GString *buffer;
+
+  buffer = g_string_new ("");
+
+  if (pretty)
+    {
+      guint i;
+
+      for (i = 0; i < (level * indent); i++)
+        g_string_append_c (buffer, priv->indent_char);
+    }
+
+  if (name && name[0] != '\0')
+    {
+      if (pretty)
+        g_string_append_printf (buffer, "\"%s\" : ", name);
+      else
+        g_string_append_printf (buffer, "\"%s\":", name);
+    }
+
+  json_node_get_value (node, &value);
+
+  switch (G_VALUE_TYPE (&value))
+    {
+    case G_TYPE_INT64:
+      g_string_append_printf (buffer, "%" G_GINT64_FORMAT, g_value_get_int64 (&value));
+      break;
+
+    case G_TYPE_STRING:
+      {
+        gchar *tmp;
+
+        tmp = json_strescape (g_value_get_string (&value));
+        g_string_append_printf (buffer, "\"%s\"", tmp);
+
+        g_free (tmp);
+      }
+      break;
+
+    case G_TYPE_DOUBLE:
+      {
+        gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+        g_string_append (buffer,
+                         g_ascii_dtostr (buf, sizeof (buf),
+                                         g_value_get_double (&value)));
+      }
+      break;
+
+    case G_TYPE_BOOLEAN:
+      g_string_append_printf (buffer, "%s",
+                              g_value_get_boolean (&value) ? "true" : "false");
+      break;
+
+    default:
+      break;
+    }
+
+  g_value_unset (&value);
+
+  if (length)
+    *length = buffer->len;
+
+  return g_string_free (buffer, FALSE);
+}
+
+static gchar *
+dump_array (JsonGenerator *generator,
+            gint           level,
+            const gchar   *name,
+            JsonArray     *array,
+            gsize         *length)
+{
+  JsonGeneratorPrivate *priv = generator->priv;
+  guint array_len = json_array_get_length (array);
+  guint i;
+  GString *buffer;
+  gboolean pretty = priv->pretty;
+  guint indent = priv->indent;
+
+  buffer = g_string_new ("");
+
+  if (pretty)
+    {
+      for (i = 0; i < (level * indent); i++)
+        g_string_append_c (buffer, priv->indent_char);
+    }
+
+  if (name && name[0] != '\0')
+    {
+      if (pretty)
+        g_string_append_printf (buffer, "\"%s\" : ", name);
+      else
+        g_string_append_printf (buffer, "\"%s\":", name);
+    }
+
+  g_string_append_c (buffer, '[');
+
+  if (pretty)
+    g_string_append_c (buffer, '\n');
+
+  for (i = 0; i < array_len; i++)
+    {
+      JsonNode *cur = json_array_get_element (array, i);
+      guint sub_level = level + 1;
+      guint j;
+      gchar *value; 
+
+      switch (JSON_NODE_TYPE (cur))
+        {
+        case JSON_NODE_NULL:
+          if (pretty)
+            {
+              for (j = 0; j < (sub_level * indent); j++)
+                g_string_append_c (buffer, priv->indent_char);
+            }
+          g_string_append (buffer, "null");
+          break;
+
+        case JSON_NODE_VALUE:
+          value = dump_value (generator, sub_level, NULL, cur, NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+
+        case JSON_NODE_ARRAY:
+          value = dump_array (generator, sub_level, NULL, json_node_get_array (cur), NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+
+        case JSON_NODE_OBJECT:
+          value = dump_object (generator, sub_level, NULL, json_node_get_object (cur), NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+        }
+
+      if ((i + 1) != array_len)
+        g_string_append_c (buffer, ',');
+
+      if (pretty)
+        g_string_append_c (buffer, '\n');
+    }
+
+  if (pretty)
+    {
+      for (i = 0; i < (level * indent); i++)
+        g_string_append_c (buffer, priv->indent_char);
+    }
+
+  g_string_append_c (buffer, ']');
+
+  if (length)
+    *length = buffer->len;
+
+  return g_string_free (buffer, FALSE);
+}
+
+static gchar *
+dump_object (JsonGenerator *generator,
+             gint           level,
+             const gchar   *name,
+             JsonObject    *object,
+             gsize         *length)
+{
+  JsonGeneratorPrivate *priv = generator->priv;
+  GList *members, *l;
+  GString *buffer;
+  gboolean pretty = priv->pretty;
+  guint indent = priv->indent;
+  guint i;
+
+  buffer = g_string_new ("");
+
+  if (pretty)
+    {
+      for (i = 0; i < (level * indent); i++)
+        g_string_append_c (buffer, priv->indent_char);
+    }
+
+  if (name && name[0] != '\0')
+    {
+      if (pretty)
+        g_string_append_printf (buffer, "\"%s\" : ", name);
+      else
+        g_string_append_printf (buffer, "\"%s\":", name);
+    }
+
+  g_string_append_c (buffer, '{');
+
+  if (pretty)
+    g_string_append_c (buffer, '\n');
+
+  members = json_object_get_members (object);
+
+  for (l = members; l != NULL; l = l->next)
+    {
+      const gchar *member_name = l->data;
+      JsonNode *cur = json_object_get_member (object, member_name);
+      guint sub_level = level + 1;
+      guint j;
+      gchar *value;
+
+      switch (JSON_NODE_TYPE (cur))
+        {
+        case JSON_NODE_NULL:
+          if (pretty)
+            {
+              for (j = 0; j < (sub_level * indent); j++)
+                g_string_append_c (buffer, priv->indent_char);
+              g_string_append_printf (buffer, "\"%s\" : null", member_name);
+            }
+          else
+            {
+              g_string_append_printf (buffer, "\"%s\":null", member_name);
+            }
+          break;
+
+        case JSON_NODE_VALUE:
+          value = dump_value (generator, sub_level, member_name, cur, NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+
+        case JSON_NODE_ARRAY:
+          value = dump_array (generator, sub_level, member_name,
+                              json_node_get_array (cur), NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+
+        case JSON_NODE_OBJECT:
+          value = dump_object (generator, sub_level, member_name,
+                               json_node_get_object (cur), NULL);
+          g_string_append (buffer, value);
+          g_free (value);
+          break;
+        }
+
+      if (l->next != NULL)
+        g_string_append_c (buffer, ',');
+
+      if (pretty)
+        g_string_append_c (buffer, '\n');
+    }
+
+  g_list_free (members);
+
+  if (pretty)
+    {
+      for (i = 0; i < (level * indent); i++)
+        g_string_append_c (buffer, priv->indent_char);
+    }
+
+  g_string_append_c (buffer, '}');
+
+  if (length)
+    *length = buffer->len;
+
+  return g_string_free (buffer, FALSE);
+}
+
+/**
+ * json_generator_new:
+ * 
+ * Creates a new #JsonGenerator. You can use this object to generate a
+ * JSON data stream starting from a data object model composed by
+ * #JsonNode<!-- -->s.
+ *
+ * Return value: the newly created #JsonGenerator instance
+ */
+JsonGenerator *
+json_generator_new (void)
+{
+  return g_object_new (JSON_TYPE_GENERATOR, NULL);
+}
+
+/**
+ * json_generator_to_data:
+ * @generator: a #JsonGenerator
+ * @length: (out): return location for the length of the returned
+ *   buffer, or %NULL
+ *
+ * Generates a JSON data stream from @generator and returns it as a
+ * buffer.
+ *
+ * Return value: a newly allocated buffer holding a JSON data stream.
+ *   Use g_free() to free the allocated resources.
+ */
+gchar *
+json_generator_to_data (JsonGenerator *generator,
+                        gsize         *length)
+{
+  JsonNode *root;
+  gchar *retval = NULL;
+
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
+
+  root = generator->priv->root;
+  if (!root)
+    {
+      if (length)
+        *length = 0;
+
+      return NULL;
+    }
+
+  switch (JSON_NODE_TYPE (root))
+    {
+    case JSON_NODE_ARRAY:
+      retval = dump_array (generator, 0, NULL, json_node_get_array (root), length);
+      break;
+
+    case JSON_NODE_OBJECT:
+      retval = dump_object (generator, 0, NULL, json_node_get_object (root), length);
+      break;
+
+    case JSON_NODE_NULL:
+      retval = g_strdup ("null");
+      if (length)
+        *length = 4;
+      break;
+
+    case JSON_NODE_VALUE:
+      retval = dump_value (generator, 0, NULL, root, length);
+      break;
+    }
+
+  return retval;
+}
+
+/**
+ * json_generator_to_file:
+ * @generator: a #JsonGenerator
+ * @filename: path to the target file
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a JSON data stream and puts it inside @filename, overwriting the
+ * current file contents. This operation is atomic.
+ *
+ * Return value: %TRUE if saving was successful.
+ */
+gboolean
+json_generator_to_file (JsonGenerator  *generator,
+                        const gchar    *filename,
+                        GError        **error)
+{
+  gchar *buffer;
+  gsize len;
+  gboolean retval;
+
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+
+  buffer = json_generator_to_data (generator, &len);
+  retval = g_file_set_contents (filename, buffer, len, error);
+  g_free (buffer);
+
+  return retval;
+}
+
+/**
+ * json_generator_to_stream:
+ * @generator: a #JsonGenerator
+ * @stream: a #GOutputStream
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Outputs JSON data and streams it (synchronously) to @stream.
+ *
+ * Return value: %TRUE if the write operation was successful, and %FALSE
+ *   on failure. In case of error, the #GError will be filled accordingly
+ *
+ * Since: 0.12
+ */
+gboolean
+json_generator_to_stream (JsonGenerator  *generator,
+                          GOutputStream  *stream,
+                          GCancellable   *cancellable,
+                          GError        **error)
+{
+  gboolean retval;
+  gchar *buffer;
+  gsize len;
+
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+  g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+
+  buffer = json_generator_to_data (generator, &len);
+  retval = g_output_stream_write (stream, buffer, len, cancellable, error);
+  g_free (buffer);
+
+  return retval;
+}
+
+/**
+ * json_generator_set_root:
+ * @generator: a #JsonGenerator
+ * @node: a #JsonNode
+ *
+ * Sets @node as the root of the JSON data stream to be serialized by
+ * the #JsonGenerator.
+ *
+ * <note>The node is copied by the generator object, so it can be safely
+ * freed after calling this function.</note>
+ */
+void
+json_generator_set_root (JsonGenerator *generator,
+                         JsonNode      *node)
+{
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  if (generator->priv->root != NULL)
+    {
+      json_node_free (generator->priv->root);
+      generator->priv->root = NULL;
+    }
+
+  if (node != NULL)
+    generator->priv->root = json_node_copy (node);
+
+  g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_ROOT]);
+}
+
+/**
+ * json_generator_get_root:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves a pointer to the root #JsonNode set using
+ * json_generator_set_root().
+ *
+ * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
+ *   is owned by the #JsonGenerator and it should not be freed
+ *
+ * Since: 0.14
+ */
+JsonNode *
+json_generator_get_root (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
+
+  return generator->priv->root;
+}
+
+/**
+ * json_generator_set_pretty:
+ * @generator: a #JsonGenerator
+ * @is_pretty: whether the generated string should be pretty printed
+ *
+ * Sets whether the generated JSON should be pretty printed, using the
+ * indentation character specified in the #JsonGenerator:indent-char
+ * property and the spacing specified in #JsonGenerator:indent property.
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_pretty (JsonGenerator *generator,
+                           gboolean       is_pretty)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  is_pretty = !!is_pretty;
+
+  if (priv->pretty != is_pretty)
+    {
+      priv->pretty = is_pretty;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_PRETTY]);
+    }
+}
+
+/**
+ * json_generator_get_pretty:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_pretty().
+ *
+ * Return value: %TRUE if the generated JSON should be pretty-printed, and
+ *   %FALSE otherwise
+ *
+ * Since: 0.14
+ */
+gboolean
+json_generator_get_pretty (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->pretty;
+}
+
+/**
+ * json_generator_set_indent:
+ * @generator: a #JsonGenerator
+ * @indent_level: the number of repetitions of the indentation character
+ *   that should be applied when pretty printing
+ *
+ * Sets the number of repetitions for each indentation level.
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_indent (JsonGenerator *generator,
+                           guint          indent_level)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  if (priv->indent != indent_level)
+    {
+      priv->indent = indent_level;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT]);
+    }
+}
+
+/**
+ * json_generator_get_indent:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_indent().
+ *
+ * Return value: the number of repetitions per indentation level
+ *
+ * Since: 0.14
+ */
+guint
+json_generator_get_indent (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->indent;
+}
+
+/**
+ * json_generator_set_indent_char:
+ * @generator: a #JsonGenerator
+ * @indent_char: a Unicode character to be used when indenting
+ *
+ * Sets the character to be used when indenting
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_indent_char (JsonGenerator *generator,
+                                gunichar       indent_char)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  if (priv->indent_char != indent_char)
+    {
+      priv->indent_char = indent_char;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT_CHAR]);
+    }
+}
+
+/**
+ * json_generator_get_indent_char:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_indent_char().
+ *
+ * Return value: the character to be used when indenting
+ *
+ * Since: 0.14
+ */
+gunichar
+json_generator_get_indent_char (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->indent_char;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-generator.h b/src/glib-jsonrpc/json-glib/json-generator.h
new file mode 100644
index 0000000..eb7cdba
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-generator.h
@@ -0,0 +1,107 @@
+/* json-generator.h - JSON streams generator
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_GENERATOR_H__
+#define __JSON_GENERATOR_H__
+
+#include <json-glib/json-types.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_GENERATOR             (json_generator_get_type ())
+#define JSON_GENERATOR(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_GENERATOR, JsonGenerator))
+#define JSON_IS_GENERATOR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_GENERATOR))
+#define JSON_GENERATOR_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), JSON_TYPE_GENERATOR, JsonGeneratorClass))
+#define JSON_IS_GENERATOR_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), JSON_TYPE_GENERATOR))
+#define JSON_GENERATOR_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), JSON_TYPE_GENERATOR, JsonGeneratorClass))
+
+typedef struct _JsonGenerator           JsonGenerator;
+typedef struct _JsonGeneratorPrivate    JsonGeneratorPrivate;
+typedef struct _JsonGeneratorClass      JsonGeneratorClass;
+
+/**
+ * JsonGenerator:
+ *
+ * JSON data streams generator. The contents of the #JsonGenerator structure
+ * are private and should only be accessed via the provided API.
+ */
+struct _JsonGenerator
+{
+  /*< private >*/
+  GObject parent_instance;
+
+  JsonGeneratorPrivate *priv;
+};
+
+/**
+ * JsonGeneratorClass:
+ *
+ * #JsonGenerator class
+ */
+struct _JsonGeneratorClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  /* padding, for future expansion */
+  void (* _json_reserved1) (void);
+  void (* _json_reserved2) (void);
+  void (* _json_reserved3) (void);
+  void (* _json_reserved4) (void);
+};
+
+GType json_generator_get_type (void) G_GNUC_CONST;
+
+JsonGenerator * json_generator_new              (void);
+
+void            json_generator_set_pretty       (JsonGenerator  *generator,
+                                                 gboolean        is_pretty);
+gboolean        json_generator_get_pretty       (JsonGenerator  *generator);
+void            json_generator_set_indent       (JsonGenerator  *generator,
+                                                 guint           indent_level);
+guint           json_generator_get_indent       (JsonGenerator  *generator);
+void            json_generator_set_indent_char  (JsonGenerator  *generator,
+                                                 gunichar        indent_char);
+gunichar        json_generator_get_indent_char  (JsonGenerator  *generator);
+void            json_generator_set_root         (JsonGenerator  *generator,
+                                                 JsonNode       *node);
+JsonNode *      json_generator_get_root         (JsonGenerator  *generator);
+
+gchar *         json_generator_to_data          (JsonGenerator  *generator,
+                                                 gsize          *length);
+gboolean        json_generator_to_file          (JsonGenerator  *generator,
+                                                 const gchar    *filename,
+                                                 GError        **error);
+gboolean        json_generator_to_stream        (JsonGenerator  *generator,
+                                                 GOutputStream  *stream,
+                                                 GCancellable   *cancellable,
+                                                 GError        **error);
+
+G_END_DECLS
+
+#endif /* __JSON_GENERATOR_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-glib.h b/src/glib-jsonrpc/json-glib/json-glib.h
new file mode 100644
index 0000000..257bcdf
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-glib.h
@@ -0,0 +1,46 @@
+/* json-glib.h: Main header
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifndef __JSON_GLIB_H__
+#define __JSON_GLIB_H__
+
+#define __JSON_GLIB_INSIDE__
+
+#include <json-glib/json-types.h>
+
+#include <json-glib/json-builder.h>
+#include <json-glib/json-generator.h>
+#include <json-glib/json-parser.h>
+#include <json-glib/json-path.h>
+#include <json-glib/json-reader.h>
+#include <json-glib/json-version.h>
+
+#include <json-glib/json-enum-types.h>
+
+#include <json-glib/json-gobject.h>
+
+#include <json-glib/json-gvariant.h>
+
+#undef __JSON_GLIB_INSIDE__
+
+#endif /* __JSON_GLIB_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-gobject-private.h b/src/glib-jsonrpc/json-glib/json-gobject-private.h
new file mode 100644
index 0000000..5369ebf
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gobject-private.h
@@ -0,0 +1,39 @@
+/* json-gobject-private.h - GObject private
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifndef __JSON_GOBJECT_PRIVATE_H__
+#define __JSON_GOBJECT_PRIVATE_H__
+
+#include "json-gobject.h"
+
+G_BEGIN_DECLS
+
+JsonNode *json_serialize_pspec   (const GValue *real_value,
+                                  GParamSpec   *pspec);
+gboolean  json_deserialize_pspec (GValue       *value,
+                                  GParamSpec   *pspec,
+                                  JsonNode     *node);
+
+G_END_DECLS
+
+#endif /* __JSON_GOBJECT_PRIVATE_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-gobject.c b/src/glib-jsonrpc/json-glib/json-gobject.c
new file mode 100644
index 0000000..073d247
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gobject.c
@@ -0,0 +1,1005 @@
+/* json-gobject.c - JSON GObject integration
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi openedhand com>
+ */
+
+/**
+ * SECTION:json-gobject
+ * @short_description: Serialize and deserialize GObjects
+ *
+ * JSON-GLib provides API for serializing and deserializing #GObject<!-- -->s
+ * to and from JSON data streams.
+ *
+ * Simple #GObject classes can be (de)serialized into JSON objects, if the
+ * properties have compatible types with the native JSON types (integers,
+ * booleans, strings, string vectors). If the class to be (de)serialized has
+ * complex data types for properties (like boxed types or other objects)
+ * then the class should implement the provided #JsonSerializable interface
+ * and its virtual functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#if 0
+#include <glib/gi18n-lib.h>
+#else
+#define _(s) s    
+#endif
+
+#include "json-types-private.h"
+#include "json-gobject-private.h"
+
+#include "json-debug.h"
+#include "json-parser.h"
+#include "json-generator.h"
+
+static gboolean
+enum_from_string (GType        type,
+                  const gchar *string,
+                  gint        *enum_value)
+{
+  GEnumClass *eclass;
+  GEnumValue *ev;
+  gchar *endptr;
+  gint value;
+  gboolean retval = TRUE;
+
+  g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
+  g_return_val_if_fail (string != NULL, 0);
+
+  value = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    *enum_value = value;
+  else
+    {
+      eclass = g_type_class_ref (type);
+      ev = g_enum_get_value_by_name (eclass, string);
+      if (!ev)
+	ev = g_enum_get_value_by_nick (eclass, string);
+
+      if (ev)
+	*enum_value = ev->value;
+      else
+        retval = FALSE;
+
+      g_type_class_unref (eclass);
+    }
+
+  return retval;
+}
+
+static gboolean
+flags_from_string (GType        type,
+                   const gchar *string,
+                   gint        *flags_value)
+{
+  GFlagsClass *fclass;
+  gchar *endptr, *prevptr;
+  guint i, j, ret, value;
+  gchar *flagstr;
+  GFlagsValue *fv;
+  const gchar *flag;
+  gunichar ch;
+  gboolean eos;
+
+  g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
+  g_return_val_if_fail (string != 0, 0);
+
+  ret = TRUE;
+
+  value = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    *flags_value = value;
+  else
+    {
+      fclass = g_type_class_ref (type);
+
+      flagstr = g_strdup (string);
+      for (value = i = j = 0; ; i++)
+	{
+	  eos = flagstr[i] == '\0';
+
+	  if (!eos && flagstr[i] != '|')
+	    continue;
+
+	  flag = &flagstr[j];
+	  endptr = &flagstr[i];
+
+	  if (!eos)
+	    {
+	      flagstr[i++] = '\0';
+	      j = i;
+	    }
+
+	  /* trim spaces */
+	  for (;;)
+	    {
+	      ch = g_utf8_get_char (flag);
+	      if (!g_unichar_isspace (ch))
+		break;
+	      flag = g_utf8_next_char (flag);
+	    }
+
+	  while (endptr > flag)
+	    {
+	      prevptr = g_utf8_prev_char (endptr);
+	      ch = g_utf8_get_char (prevptr);
+	      if (!g_unichar_isspace (ch))
+		break;
+	      endptr = prevptr;
+	    }
+
+	  if (endptr > flag)
+	    {
+	      *endptr = '\0';
+	      fv = g_flags_get_value_by_name (fclass, flag);
+
+	      if (!fv)
+		fv = g_flags_get_value_by_nick (fclass, flag);
+
+	      if (fv)
+		value |= fv->value;
+	      else
+		{
+		  ret = FALSE;
+		  break;
+		}
+	    }
+
+	  if (eos)
+	    {
+	      *flags_value = value;
+	      break;
+	    }
+	}
+
+      g_free (flagstr);
+
+      g_type_class_unref (fclass);
+    }
+
+  return ret;
+}
+
+static GObject *
+json_gobject_new (GType       gtype,
+                  JsonObject *object)
+{
+  JsonSerializableIface *iface = NULL;
+  JsonSerializable *serializable = NULL;
+  gboolean find_property;
+  gboolean deserialize_property;
+  gboolean set_property;
+  GList *members, *members_left, *l;
+  guint n_members;
+  GObjectClass *klass;
+  GObject *retval;
+  GArray *construct_params;
+  gint i;
+
+  klass = g_type_class_ref (gtype);
+
+  n_members = json_object_get_size (object);
+  members = json_object_get_members (object);
+  members_left = NULL;
+
+  /* first pass: construct-only properties; here we cannot use Serializable
+   * because we don't have an instance yet; we use the default implementation
+   * of json_deserialize_pspec() to deserialize known types
+   *
+   * FIXME - find a way to allow deserialization for these properties
+   */
+  construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
+
+  for (l = members; l != NULL; l = l->next)
+    {
+      const gchar *member_name = l->data;
+      GParamSpec *pspec;
+      GParameter param = { NULL, };
+      JsonNode *val;
+      gboolean res = FALSE;
+
+      pspec = g_object_class_find_property (klass, member_name);
+      if (!pspec)
+        goto next_member;
+
+      /* we only apply construct-only properties here */
+      if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0)
+        goto next_member;
+
+      if (!(pspec->flags & G_PARAM_WRITABLE))
+        goto next_member;
+
+      g_value_init (&param.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+
+      val = json_object_get_member (object, member_name);
+      res = json_deserialize_pspec (&param.value, pspec, val);
+      if (!res)
+	{
+	  g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
+		     pspec->name, G_VALUE_TYPE_NAME (&param.value), g_type_name (gtype));
+
+	  g_value_unset (&param.value);
+	}
+      else
+        {
+          param.name = g_strdup (pspec->name);
+
+          g_array_append_val (construct_params, param);
+
+          continue;
+        }
+
+    next_member:
+      members_left = g_list_prepend (members_left, l->data);
+    }
+
+  retval = g_object_newv (gtype,
+                          construct_params->len,
+                          (GParameter *) construct_params->data);
+
+  /* free the contents of the GArray */
+  for (i = 0; i < construct_params->len; i++)
+    {
+      GParameter *param = &g_array_index (construct_params, GParameter, i);
+
+      g_free ((gchar *) param->name);
+      g_value_unset (&param->value);
+    }
+
+  g_array_free (construct_params, TRUE);
+  g_list_free (members);
+
+  /* we use g_list_prepend() above, but we want to maintain
+   * the ordering of json_object_get_members() here
+   */
+  members = g_list_reverse (members_left);
+
+  /* do the Serializable type check once */
+  if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
+    {
+      serializable = JSON_SERIALIZABLE (retval);
+      iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
+      find_property = (iface->find_property != NULL);
+      deserialize_property = (iface->deserialize_property != NULL);
+      set_property = (iface->set_property != NULL);
+    }
+  else
+    {
+      find_property = FALSE;
+      deserialize_property = FALSE;
+      set_property = FALSE;
+    }
+
+  g_object_freeze_notify (retval);
+
+  for (l = members; l != NULL; l = l->next)
+    {
+      const gchar *member_name = l->data;
+      GParamSpec *pspec;
+      JsonNode *val;
+      GValue value = { 0, };
+      gboolean res = FALSE;
+
+      if (find_property)
+        pspec = json_serializable_find_property (serializable, member_name);
+      else
+        pspec = g_object_class_find_property (klass, member_name);
+
+      if (pspec == NULL)
+        continue;
+
+      /* we should have dealt with these above */
+      if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+        continue;
+
+      if (!(pspec->flags & G_PARAM_WRITABLE))
+        continue;
+
+      g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+
+      val = json_object_get_member (object, member_name);
+
+      if (deserialize_property)
+        {
+          JSON_NOTE (GOBJECT, "Using JsonSerializable for property '%s'", pspec->name);
+          res = iface->deserialize_property (serializable, pspec->name,
+                                             &value,
+                                             pspec,
+                                             val);
+        }
+
+      if (!res)
+        {
+          JSON_NOTE (GOBJECT, "Using json_deserialize_pspec for property '%s'", pspec->name);
+          res = json_deserialize_pspec (&value, pspec, val);
+        }
+
+      if (res)
+        {
+          JSON_NOTE (GOBJECT, "Calling set_property('%s', '%s')",
+                     pspec->name,
+                     g_type_name (G_VALUE_TYPE (&value)));
+
+          if (set_property)
+            json_serializable_set_property (serializable, pspec, &value);
+          else
+            g_object_set_property (retval, pspec->name, &value);
+        }
+      else
+	g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
+		   pspec->name, g_type_name (G_VALUE_TYPE (&value)), g_type_name (gtype));
+
+      g_value_unset (&value);
+    }
+
+  g_list_free (members);
+
+  g_object_thaw_notify (retval);
+
+  g_type_class_unref (klass);
+
+  return retval;
+}
+
+static JsonObject *
+json_gobject_dump (GObject *gobject)
+{
+  JsonSerializableIface *iface = NULL;
+  JsonSerializable *serializable = NULL;
+  gboolean list_properties = FALSE;
+  gboolean serialize_property = FALSE;
+  gboolean get_property = FALSE;
+  JsonObject *object;
+  GParamSpec **pspecs;
+  guint n_pspecs, i;
+
+  if (JSON_IS_SERIALIZABLE (gobject))
+    {
+      serializable = JSON_SERIALIZABLE (gobject);
+      iface = JSON_SERIALIZABLE_GET_IFACE (gobject);
+      list_properties = (iface->list_properties != NULL);
+      serialize_property = (iface->serialize_property != NULL);
+      get_property = (iface->get_property != NULL);
+    }
+
+  object = json_object_new ();
+
+  if (list_properties)
+    pspecs = json_serializable_list_properties (serializable, &n_pspecs);
+  else
+    pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (gobject), &n_pspecs);
+
+  for (i = 0; i < n_pspecs; i++)
+    {
+      GParamSpec *pspec = pspecs[i];
+      GValue value = { 0, };
+      JsonNode *node = NULL;
+
+      /* read only what we can */
+      if (!(pspec->flags & G_PARAM_READABLE))
+        continue;
+
+      g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+
+      if (get_property)
+        json_serializable_get_property (serializable, pspec, &value);
+      else
+        g_object_get_property (gobject, pspec->name, &value);
+
+      /* if there is a serialization vfunc, then it is completely responsible
+       * for serializing the property, possibly by calling the implementation
+       * of the default JsonSerializable interface through chaining up
+       */
+      if (serialize_property)
+        {
+          node = iface->serialize_property (serializable, pspec->name,
+                                            &value,
+                                            pspec);
+        }
+      /* skip if the value is the default for the property */
+      else if (!g_param_value_defaults (pspec, &value))
+        node = json_serialize_pspec (&value, pspec);
+
+      if (node)
+        json_object_set_member (object, pspec->name, node);
+
+      g_value_unset (&value);
+    }
+
+  g_free (pspecs);
+
+  return object;
+}
+
+gboolean
+json_deserialize_pspec (GValue     *value,
+                        GParamSpec *pspec,
+                        JsonNode   *node)
+{
+  GValue node_value = { 0, };
+  gboolean retval = FALSE;
+
+  if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_BOXED)
+    {
+      JsonNodeType node_type = json_node_get_node_type (node);
+      GType boxed_type = G_VALUE_TYPE (value);
+
+      if (json_boxed_can_deserialize (boxed_type, node_type))
+        {
+          gpointer boxed = json_boxed_deserialize (boxed_type, node);
+
+          g_value_take_boxed (value, boxed);
+
+          return TRUE;
+        }
+    }
+
+  switch (JSON_NODE_TYPE (node))
+    {
+    case JSON_NODE_OBJECT:
+      if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT))
+        {
+          GObject *object;
+
+          object = json_gobject_new (G_VALUE_TYPE (value), json_node_get_object (node));
+          if (object != NULL)
+            g_value_take_object (value, object);
+          else
+            g_value_set_object (value, NULL);
+
+          retval = TRUE;
+        }
+      break;
+
+    case JSON_NODE_ARRAY:
+      if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        {
+          JsonArray *array = json_node_get_array (node);
+          guint i, array_len = json_array_get_length (array);
+          GPtrArray *str_array = g_ptr_array_sized_new (array_len + 1);
+
+          for (i = 0; i < array_len; i++)
+            {
+              JsonNode *val = json_array_get_element (array, i);
+
+              if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE)
+                continue;
+
+              if (json_node_get_string (val) != NULL)
+                g_ptr_array_add (str_array, (gpointer) json_node_get_string (val));
+            }
+
+          g_ptr_array_add (str_array, NULL);
+
+          g_value_set_boxed (value, str_array->pdata);
+
+          g_ptr_array_free (str_array, TRUE);
+
+          retval = TRUE;
+        }
+      break;
+
+    case JSON_NODE_VALUE:
+      json_node_get_value (node, &node_value);
+#if 0
+      {
+        gchar *node_str = g_strdup_value_contents (&node_value);
+        g_debug ("%s: value type '%s' := node value type '%s' -> '%s'",
+                 G_STRLOC,
+                 g_type_name (G_VALUE_TYPE (value)),
+                 g_type_name (G_VALUE_TYPE (&node_value)),
+                 node_str);
+        g_free (node_str);
+      }
+#endif
+
+      switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
+        {
+        case G_TYPE_BOOLEAN:
+        case G_TYPE_INT64:
+        case G_TYPE_STRING:
+	  if (G_VALUE_HOLDS (&node_value, G_VALUE_TYPE (value)))
+	    {
+	      g_value_copy (&node_value, value);
+	      retval = TRUE;
+	    }
+          break;
+
+        case G_TYPE_INT:
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_int (value, (gint) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+          break;
+
+        case G_TYPE_CHAR:
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_char (value, (gchar) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+          break;
+
+        case G_TYPE_UINT:
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_uint (value, (guint) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+          break;
+
+        case G_TYPE_UCHAR:
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_uchar (value, (guchar) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+          break;
+
+        case G_TYPE_DOUBLE:
+
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
+	    {
+	      g_value_set_double (value, g_value_get_double (&node_value));
+	      retval = TRUE;
+	    }
+	  else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_double (value, (gdouble) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+
+          break;
+
+        case G_TYPE_FLOAT:
+	  if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE))
+	    {
+	      g_value_set_float (value, (gfloat) g_value_get_double (&node_value));
+	      retval = TRUE;
+	    }
+	  else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+	    {
+	      g_value_set_float (value, (gfloat) g_value_get_int64 (&node_value));
+	      retval = TRUE;
+	    }
+
+          break;
+
+        case G_TYPE_ENUM:
+          {
+            gint enum_value = 0;
+
+            if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+              {
+                enum_value = g_value_get_int64 (&node_value);
+                retval = TRUE;
+              }
+            else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
+              {
+                retval = enum_from_string (G_VALUE_TYPE (value),
+                                           g_value_get_string (&node_value),
+                                           &enum_value);
+              }
+
+            if (retval)
+              g_value_set_enum (value, enum_value);
+          }
+          break;
+
+        case G_TYPE_FLAGS:
+          {
+            gint flags_value = 0;
+
+            if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64))
+              {
+                flags_value = g_value_get_int64 (&node_value);
+                retval = TRUE;
+              }
+            else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING))
+              {
+                retval = flags_from_string (G_VALUE_TYPE (value),
+                                            g_value_get_string (&node_value),
+                                            &flags_value);
+              }
+
+            if (retval)
+              g_value_set_flags (value, flags_value);
+          }
+          break;
+
+        default:
+          retval = FALSE;
+          break;
+        }
+
+      g_value_unset (&node_value);
+      break;
+
+    case JSON_NODE_NULL:
+      if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING)
+	{
+	  g_value_set_string (value, NULL);
+	  retval = TRUE;
+	}
+      else if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_OBJECT)
+	{
+	  g_value_set_object (value, NULL);
+	  retval = TRUE;
+	}
+      else
+	retval = FALSE;
+
+      break;
+    }
+
+  return retval;
+}
+
+JsonNode *
+json_serialize_pspec (const GValue *real_value,
+                      GParamSpec   *pspec)
+{
+  JsonNode *retval = NULL;
+  GValue value = { 0, };
+  JsonNodeType node_type;
+
+  switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (real_value)))
+    {
+    case G_TYPE_INT64:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_DOUBLE:
+      /* JSON native types */
+      retval = json_node_new (JSON_NODE_VALUE);
+      g_value_init (&value, G_VALUE_TYPE (real_value));
+      g_value_copy (real_value, &value);
+      json_node_set_value (retval, &value);
+      g_value_unset (&value);
+      break;
+
+    case G_TYPE_STRING:
+      /* strings might be NULL, so we handle it differently */
+      if (!g_value_get_string (real_value))
+        retval = json_node_new (JSON_NODE_NULL);
+      else
+        {
+          retval = json_node_new (JSON_NODE_VALUE);
+          json_node_set_string (retval, g_value_get_string (real_value));
+          break;
+        }
+      break;
+
+    case G_TYPE_INT:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_int (real_value));
+      break;
+
+    case G_TYPE_FLOAT:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_double (retval, g_value_get_float (real_value));
+      break;
+
+    case G_TYPE_BOXED:
+      if (G_VALUE_HOLDS (real_value, G_TYPE_STRV))
+        {
+          gchar **strv = g_value_get_boxed (real_value);
+          gint i, strv_len;
+          JsonArray *array;
+
+          strv_len = g_strv_length (strv);
+          array = json_array_sized_new (strv_len);
+
+          for (i = 0; i < strv_len; i++)
+            {
+              JsonNode *str = json_node_new (JSON_NODE_VALUE);
+
+              json_node_set_string (str, strv[i]);
+              json_array_add_element (array, str);
+            }
+
+          retval = json_node_new (JSON_NODE_ARRAY);
+          json_node_take_array (retval, array);
+        }
+      else if (json_boxed_can_serialize (G_VALUE_TYPE (real_value), &node_type))
+        {
+          gpointer boxed = g_value_get_boxed (real_value);
+
+          retval = json_boxed_serialize (G_VALUE_TYPE (real_value), boxed);
+        }
+      else
+        g_warning ("Boxed type '%s' is not handled by JSON-GLib",
+                   g_type_name (G_VALUE_TYPE (real_value)));
+      break;
+
+    case G_TYPE_UINT:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_uint (real_value));
+      break;
+
+    case G_TYPE_LONG:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_long (real_value));
+      break;
+
+    case G_TYPE_ULONG:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_long (real_value));
+      break;
+
+    case G_TYPE_CHAR:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_char (real_value));
+      break;
+
+    case G_TYPE_UCHAR:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_uchar (real_value));
+      break;
+
+    case G_TYPE_ENUM:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_enum (real_value));
+      break;
+
+    case G_TYPE_FLAGS:
+      retval = json_node_new (JSON_NODE_VALUE);
+      json_node_set_int (retval, g_value_get_flags (real_value));
+      break;
+
+    case G_TYPE_OBJECT:
+      {
+        GObject *object = g_value_get_object (real_value);
+
+        if (object != NULL)
+          {
+            retval = json_node_new (JSON_NODE_OBJECT);
+            json_node_take_object (retval, json_gobject_dump (object));
+          }
+        else
+          retval = json_node_new (JSON_NODE_NULL);
+      }
+      break;
+
+    case G_TYPE_NONE:
+      retval = json_node_new (JSON_NODE_NULL);
+      break;
+
+    default:
+      g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
+      break;
+    }
+
+  return retval;
+}
+
+/**
+ * json_gobject_deserialize:
+ * @gtype: the type of the #GObject to create
+ * @node: a #JsonNode of type %JSON_NODE_OBJECT describing the
+ *   instance of type @gtype
+ *
+ * Creates a new #GObject of type @gtype, and constructs it
+ * using the members of the passed #JsonObject
+ *
+ * Return value: (transfer full): The newly created #GObject
+ *   instance. Use g_object_unref() to free the resources
+ *   allocated by this function
+ *
+ * Since: 0.10
+ */
+GObject *
+json_gobject_deserialize (GType     gtype,
+                          JsonNode *node)
+{
+  g_return_val_if_fail (g_type_is_a (gtype, G_TYPE_OBJECT), NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
+
+  return json_gobject_new (gtype, json_node_get_object (node));
+}
+
+/**
+ * json_gobject_serialize:
+ * @gobject: a #GObject
+ *
+ * Creates a #JsonNode representing the passed #GObject
+ * instance. Each member of the returned JSON object will
+ * map to a property of the #GObject
+ *
+ * Return value: (transfer full): the newly created #JsonNode
+ *   of type %JSON_NODE_OBJECT. Use json_node_free() to free
+ *   the resources allocated by this function
+ *
+ * Since: 0.10
+ */
+JsonNode *
+json_gobject_serialize (GObject *gobject)
+{
+  JsonNode *retval;
+
+  g_return_val_if_fail (G_IS_OBJECT (gobject), NULL);
+
+  retval = json_node_new (JSON_NODE_OBJECT);
+  json_node_take_object (retval, json_gobject_dump (gobject));
+
+  return retval;
+}
+
+/**
+ * json_construct_gobject:
+ * @gtype: the #GType of object to construct
+ * @data: a JSON data stream
+ * @length: length of the data stream
+ * @error: return location for a #GError, or %NULL
+ *
+ * Deserializes a JSON data stream and creates the corresponding
+ * #GObject class. If @gtype implements the #JsonSerializableIface
+ * interface, it will be asked to deserialize all the JSON members
+ * into the respective properties; otherwise, the default implementation
+ * will be used to translate the compatible JSON native types.
+ *
+ * Note: the JSON data stream must be an object declaration.
+ *
+ * Return value: (transfer full): a #GObject or %NULL
+ *
+ * Since: 0.4
+ *
+ * Deprecated: 0.10: Use json_gobject_from_data() instead
+ */
+GObject *
+json_construct_gobject (GType         gtype,
+                        const gchar  *data,
+                        gsize         length,
+                        GError      **error)
+{
+  return json_gobject_from_data (gtype, data, strlen (data), error);
+}
+
+/**
+ * json_gobject_from_data:
+ * @gtype: the #GType of object to construct
+ * @data: a JSON data stream
+ * @length: length of the data stream, or -1 if it is NUL-terminated
+ * @error: return location for a #GError, or %NULL
+ *
+ * Deserializes a JSON data stream and creates the corresponding
+ * #GObject class. If @gtype implements the #JsonSerializableIface
+ * interface, it will be asked to deserialize all the JSON members
+ * into the respective properties; otherwise, the default implementation
+ * will be used to translate the compatible JSON native types.
+ *
+ * Note: the JSON data stream must be an object declaration.
+ *
+ * Return value: (transfer full): a #GObject or %NULL
+ *
+ * Since: 0.10
+ */
+GObject *
+json_gobject_from_data (GType         gtype,
+                        const gchar  *data,
+                        gssize        length,
+                        GError      **error)
+{
+  JsonParser *parser;
+  JsonNode *root;
+  GError *parse_error;
+  GObject *retval;
+
+  g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
+  g_return_val_if_fail (data != NULL, NULL);
+
+  if (length < 0)
+    length = strlen (data);
+
+  parser = json_parser_new ();
+
+  parse_error = NULL;
+  json_parser_load_from_data (parser, data, length, &parse_error);
+  if (parse_error)
+    {
+      g_propagate_error (error, parse_error);
+      g_object_unref (parser);
+      return NULL;
+    }
+
+  root = json_parser_get_root (parser);
+  if (root == NULL || JSON_NODE_TYPE (root) != JSON_NODE_OBJECT)
+    {
+      /* translators: the %s is the name of the data structure */
+      g_set_error (error, JSON_PARSER_ERROR,
+                   JSON_PARSER_ERROR_PARSE,
+                   _("Expecting a JSON object, but the root node is of type `%s'"),
+                   json_node_type_name (root));
+      g_object_unref (parser);
+      return NULL;
+    }
+
+  retval = json_gobject_deserialize (gtype, root);
+
+  g_object_unref (parser);
+
+  return retval;
+}
+
+/**
+ * json_serialize_gobject:
+ * @gobject: a #GObject
+ * @length: (out): return value for the length of the buffer, or %NULL
+ *
+ * Serializes a #GObject into a JSON data stream. If @gobject implements
+ * the #JsonSerializableIface interface, it will be asked to serizalize all
+ * its properties; otherwise, the default implementation will be use to
+ * translate the compatible types into JSON native types.
+ *
+ * Return value: a JSON data stream representing the passed #GObject
+ *
+ * Deprecated: 0.10: Use json_gobject_to_data() instead
+ */
+gchar *
+json_serialize_gobject (GObject *gobject,
+                        gsize   *length)
+{
+  return json_gobject_to_data (gobject, length);
+}
+
+/**
+ * json_gobject_to_data:
+ * @gobject: a #GObject
+ * @length: (out): return value for the length of the buffer, or %NULL
+ *
+ * Serializes a #GObject into a JSON data stream, iterating recursively
+ * over each property.
+ *
+ * If @gobject implements the #JsonSerializableIface interface, it will
+ * be asked to serialize all its properties; otherwise, the default
+ * implementation will be use to translate the compatible types into
+ * JSON native types.
+ *
+ * Return value: a JSON data stream representing the passed #GObject
+ *
+ * Since: 0.10
+ */
+gchar *
+json_gobject_to_data (GObject *gobject,
+                      gsize   *length)
+{
+  JsonGenerator *gen;
+  JsonNode *root;
+  gchar *data;
+
+  g_return_val_if_fail (G_OBJECT (gobject), NULL);
+
+  root = json_gobject_serialize (gobject);
+
+  gen = g_object_new (JSON_TYPE_GENERATOR,
+                      "root", root,
+                      "pretty", TRUE,
+                      "indent", 2,
+                      NULL);
+
+  data = json_generator_to_data (gen, length);
+  g_object_unref (gen);
+
+  json_node_free (root);
+
+  return data;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-gobject.h b/src/glib-jsonrpc/json-glib/json-gobject.h
new file mode 100644
index 0000000..2e06d88
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gobject.h
@@ -0,0 +1,182 @@
+/* json-gobject.h - JSON GObject integration
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifndef __JSON_GOBJECT_H__
+#define __JSON_GOBJECT_H__
+
+#include <json-glib/json-types.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_SERIALIZABLE                  (json_serializable_get_type ())
+#define JSON_SERIALIZABLE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_SERIALIZABLE, JsonSerializable))
+#define JSON_IS_SERIALIZABLE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_SERIALIZABLE))
+#define JSON_SERIALIZABLE_GET_IFACE(obj)        (G_TYPE_INSTANCE_GET_INTERFACE ((obj), JSON_TYPE_SERIALIZABLE, JsonSerializableIface))
+
+typedef struct _JsonSerializable        JsonSerializable; /* dummy */
+typedef struct _JsonSerializableIface   JsonSerializableIface;
+
+/**
+ * JsonSerializableIface:
+ * @serialize_property: virtual function for serializing a #GObject property
+ *   into a #JsonNode
+ * @deserialize_property: virtual function for deserializing a #JsonNode
+ *   into a #GObject property
+ * @find_property: virtual function for finding a property definition using
+ *   its name
+ * @list_properties: virtual function for listing the installed property
+ *   definitions
+ * @set_property: virtual function for setting a property
+ * @get_property: virtual function for getting a property
+ *
+ * Interface that allows serializing and deserializing #GObject<!-- -->s
+ * with properties storing complex data types. The json_serialize_gobject()
+ * function will check if the passed #GObject implements this interface,
+ * so it can also be used to override the default property serialization
+ * sequence.
+ */
+struct _JsonSerializableIface
+{
+  /*< private >*/
+  GTypeInterface g_iface;
+
+  /*< public >*/
+  JsonNode *(* serialize_property)   (JsonSerializable *serializable,
+                                      const gchar      *property_name,
+                                      const GValue     *value,
+                                      GParamSpec       *pspec);
+  gboolean  (* deserialize_property) (JsonSerializable *serializable,
+                                      const gchar      *property_name,
+                                      GValue           *value,
+                                      GParamSpec       *pspec,
+                                      JsonNode         *property_node);
+
+  GParamSpec * (* find_property)       (JsonSerializable *serializable,
+                                        const char       *name);
+  GParamSpec **(* list_properties)     (JsonSerializable *serializable,
+                                        guint            *n_pspecs);
+  void         (* set_property)        (JsonSerializable *serializable,
+                                        GParamSpec       *pspec,
+                                        const GValue     *value);
+  void         (* get_property)        (JsonSerializable *serializable,
+                                        GParamSpec       *pspec,
+                                        GValue           *value);
+};
+
+GType     json_serializable_get_type (void) G_GNUC_CONST;
+
+JsonNode *json_serializable_serialize_property           (JsonSerializable *serializable,
+                                                          const gchar      *property_name,
+                                                          const GValue     *value,
+                                                          GParamSpec       *pspec);
+gboolean  json_serializable_deserialize_property         (JsonSerializable *serializable,
+                                                          const gchar      *property_name,
+                                                          GValue           *value,
+                                                          GParamSpec       *pspec,
+                                                          JsonNode         *property_node);
+
+GParamSpec *    json_serializable_find_property         (JsonSerializable *serializable,
+                                                         const char       *name);
+GParamSpec **   json_serializable_list_properties       (JsonSerializable *serializable,
+                                                         guint            *n_pspecs);
+void            json_serializable_set_property          (JsonSerializable *serializable,
+                                                         GParamSpec       *pspec,
+                                                         const GValue     *value);
+void            json_serializable_get_property          (JsonSerializable *serializable,
+                                                         GParamSpec       *pspec,
+                                                         GValue           *value);
+
+JsonNode *json_serializable_default_serialize_property   (JsonSerializable *serializable,
+                                                          const gchar      *property_name,
+                                                          const GValue     *value,
+                                                          GParamSpec       *pspec);
+gboolean  json_serializable_default_deserialize_property (JsonSerializable *serializable,
+                                                          const gchar      *property_name,
+                                                          GValue           *value,
+                                                          GParamSpec       *pspec,
+                                                          JsonNode         *property_node);
+
+/**
+ * JsonBoxedSerializeFunc:
+ * @boxed: a #GBoxed
+ *
+ * Serializes the passed #GBoxed and stores it inside a #JsonNode
+ *
+ * Return value: the newly created #JsonNode
+ *
+ * Since: 0.10
+ */
+typedef JsonNode *(* JsonBoxedSerializeFunc) (gconstpointer boxed);
+
+/**
+ * JsonBoxedDeserializeFunc:
+ * @node: a #JsonNode
+ *
+ * Deserializes the contents of the passed #JsonNode into a #GBoxed
+ *
+ * Return value: the newly created boxed type
+ *
+ * Since: 0.10
+ */
+typedef gpointer (* JsonBoxedDeserializeFunc) (JsonNode *node);
+
+void      json_boxed_register_serialize_func   (GType                    gboxed_type,
+                                                JsonNodeType             node_type,
+                                                JsonBoxedSerializeFunc   serialize_func);
+void      json_boxed_register_deserialize_func (GType                    gboxed_type,
+                                                JsonNodeType             node_type,
+                                                JsonBoxedDeserializeFunc deserialize_func);
+gboolean  json_boxed_can_serialize             (GType                    gboxed_type,
+                                                JsonNodeType            *node_type);
+gboolean  json_boxed_can_deserialize           (GType                    gboxed_type,
+                                                JsonNodeType             node_type);
+JsonNode *json_boxed_serialize                 (GType                    gboxed_type,
+                                                gconstpointer            boxed);
+gpointer  json_boxed_deserialize               (GType                    gboxed_type,
+                                                JsonNode                *node);
+
+JsonNode *json_gobject_serialize               (GObject                 *gobject);
+GObject * json_gobject_deserialize             (GType                    gtype,
+                                                JsonNode                *node);
+
+GObject * json_gobject_from_data               (GType                    gtype,
+                                                const gchar             *data,
+                                                gssize                   length,
+                                                GError                 **error);
+gchar *   json_gobject_to_data                 (GObject                 *gobject,
+                                                gsize                   *length);
+
+#ifndef JSON_DISABLE_DEPRECATED
+GObject * json_construct_gobject               (GType                    gtype,
+                                                const gchar             *data,
+                                                gsize                    length,
+                                                GError                 **error) G_GNUC_DEPRECATED;
+gchar *   json_serialize_gobject               (GObject                 *gobject,
+                                                gsize                   *length) G_GNUC_MALLOC G_GNUC_DEPRECATED;
+#endif /* JSON_DISABLE_DEPRECATED */
+
+
+G_END_DECLS
+
+#endif /* __JSON_GOBJECT_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-gvariant.c b/src/glib-jsonrpc/json-glib/json-gvariant.c
new file mode 100644
index 0000000..dc40ec5
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gvariant.c
@@ -0,0 +1,1341 @@
+/* json-gvariant.c - JSON GVariant integration
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Author:
+ *   Eduardo Lima Mitev  <elima igalia com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#if 0
+#include <glib/gi18n-lib.h>
+#else
+#define _(s) s
+#endif
+
+#include "json-gvariant.h"
+
+/**
+ * SECTION:json-gvariant
+ * @short_description: Serialize and deserialize GVariant types
+ * @Title: JSON GVariant Integration
+ *
+ * Use json_gvariant_serialize() and json_gvariant_serialize_data() to
+ * convert from any #GVariant value to a #JsonNode tree or its string
+ * representation.
+ *
+ * Use json_gvariant_deserialize() and json_gvariant_deserialize_data() to
+ * obtain the #GVariant value from a #JsonNode tree or directly from a JSON
+ * string.
+ * Since many #GVariant data types cannot be directly represented as
+ * JSON, a #GVariant type string (signature) should be provided to these
+ * methods in order to obtain a correct, type-contrained result.
+ * If no signature is provided, conversion can still be done, but the
+ * resulting #GVariant value will be "guessed" from the JSON data types,
+ * according to the following table:
+ *
+ * <table frame='all'><title>Default JSON to GVariant conversion (without signature constrains)</title>
+ *  <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ *   <thead>
+ *     <row>
+ *       <entry>JSON</entry>
+ *       <entry>GVariant</entry>
+ *     </row>
+ *   </thead>
+ *   <tfoot>
+ *    <row>
+ *     <entry>string</entry>
+ *     <entry>string (s)</entry>
+ *    </row>
+ *    <row>
+ *     <entry>int64</entry>
+ *     <entry>int64 (x)</entry>
+ *    </row>
+ *    <row>
+ *     <entry>boolean</entry>
+ *     <entry>boolean (b)</entry>
+ *    </row>
+ *    <row>
+ *     <entry>double</entry>
+ *     <entry>double (d)</entry>
+ *    </row>
+ *    <row>
+ *     <entry>array</entry>
+ *     <entry>array of variants (av)</entry>
+ *    </row>
+ *    <row>
+ *     <entry>object</entry>
+ *     <entry>dictionary of string-variant (a{sv})</entry>
+ *    </row>
+ *    <row>
+ *     <entry>null</entry>
+ *     <entry>maybe variant (mv)</entry>
+ *    </row>
+ *   </tfoot>
+ *  </tgroup>
+ * </table>
+ */
+
+/* custom extension to the GVariantClass enumeration to differentiate
+ * a single dictionary entry from an array of dictionary entries
+ */
+#define JSON_G_VARIANT_CLASS_DICTIONARY 'c'
+
+typedef void (* GVariantForeachFunc) (GVariant *variant_child,
+                                      gpointer  user_data);
+
+static GVariant * json_to_gvariant_recurse (JsonNode      *json_node,
+                                            const gchar  **signature,
+                                            GError       **error);
+
+/* ========================================================================== */
+/* GVariant to JSON */
+/* ========================================================================== */
+
+static void
+gvariant_foreach (GVariant            *variant,
+                  GVariantForeachFunc  func,
+                  gpointer             user_data)
+{
+  GVariantIter iter;
+  GVariant *variant_child;
+
+  g_variant_iter_init (&iter, variant);
+  while ((variant_child = g_variant_iter_next_value (&iter)) != NULL)
+    {
+      func (variant_child, user_data);
+      g_variant_unref (variant_child);
+    }
+}
+
+static void
+gvariant_to_json_array_foreach (GVariant *variant_child,
+                                gpointer  user_data)
+{
+  JsonArray *array = user_data;
+  JsonNode *json_child;
+
+  json_child = json_gvariant_serialize (variant_child);
+  json_array_add_element (array, json_child);
+}
+
+static JsonNode *
+gvariant_to_json_array (GVariant *variant)
+{
+  JsonArray *array;
+  JsonNode *json_node;
+
+  array = json_array_new ();
+  json_node = json_node_new (JSON_NODE_ARRAY);
+  json_node_set_array (json_node, array);
+  json_array_unref (array);
+
+  gvariant_foreach (variant,
+                    gvariant_to_json_array_foreach,
+                    array);
+
+  return json_node;
+}
+
+static gchar *
+gvariant_simple_to_string (GVariant *variant)
+{
+  GVariantClass class;
+  gchar *str;
+
+  class = g_variant_classify (variant);
+  switch (class)
+    {
+    case G_VARIANT_CLASS_BOOLEAN:
+      if (g_variant_get_boolean (variant))
+        str = g_strdup ("true");
+      else
+        str = g_strdup ("false");
+      break;
+
+    case G_VARIANT_CLASS_BYTE:
+      str = g_strdup_printf ("%u", g_variant_get_byte (variant));
+      break;
+    case G_VARIANT_CLASS_INT16:
+      str = g_strdup_printf ("%d", g_variant_get_int16 (variant));
+      break;
+    case G_VARIANT_CLASS_UINT16:
+      str = g_strdup_printf ("%u", g_variant_get_uint16 (variant));
+      break;
+    case G_VARIANT_CLASS_INT32:
+      str = g_strdup_printf ("%d", g_variant_get_int32 (variant));
+      break;
+    case G_VARIANT_CLASS_UINT32:
+      str = g_strdup_printf ("%u", g_variant_get_uint32 (variant));
+      break;
+    case G_VARIANT_CLASS_INT64:
+      str = g_strdup_printf ("%" G_GINT64_FORMAT,
+                             g_variant_get_int64 (variant));
+      break;
+    case G_VARIANT_CLASS_UINT64:
+      str = g_strdup_printf ("%" G_GUINT64_FORMAT,
+                             g_variant_get_uint64 (variant));
+      break;
+    case G_VARIANT_CLASS_HANDLE:
+      str = g_strdup_printf ("%d", g_variant_get_handle (variant));
+      break;
+
+    case G_VARIANT_CLASS_DOUBLE:
+      {
+        gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+        g_ascii_formatd (buf,
+                         G_ASCII_DTOSTR_BUF_SIZE,
+                         "%f",
+                         g_variant_get_double (variant));
+
+        str = g_strdup (buf);
+        break;
+      }
+
+    case G_VARIANT_CLASS_STRING:
+    case G_VARIANT_CLASS_OBJECT_PATH:
+    case G_VARIANT_CLASS_SIGNATURE:
+      str = g_strdup (g_variant_get_string (variant, NULL));
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return str;
+}
+
+static JsonNode *
+gvariant_dict_entry_to_json (GVariant  *variant, gchar **member_name)
+{
+  GVariant *member;
+  GVariant *value;
+  JsonNode *json_node;
+
+  member = g_variant_get_child_value (variant, 0);
+  *member_name = gvariant_simple_to_string (member);
+
+  value = g_variant_get_child_value (variant, 1);
+  json_node = json_gvariant_serialize (value);
+
+  g_variant_unref (member);
+  g_variant_unref (value);
+
+  return json_node;
+}
+
+static void
+gvariant_to_json_object_foreach (GVariant *variant_child, gpointer  user_data)
+{
+  gchar *member_name;
+  JsonNode *json_child;
+  JsonObject *object = (JsonObject *) user_data;
+
+  json_child = gvariant_dict_entry_to_json (variant_child, &member_name);
+  json_object_set_member (object, member_name, json_child);
+  g_free (member_name);
+}
+
+static JsonNode *
+gvariant_to_json_object (GVariant *variant)
+{
+  JsonNode *json_node;
+  JsonObject *object;
+
+  json_node = json_node_new (JSON_NODE_OBJECT);
+  object = json_object_new ();
+  json_node_set_object (json_node, object);
+  json_object_unref (object);
+
+  gvariant_foreach (variant,
+                    gvariant_to_json_object_foreach,
+                    object);
+
+  return json_node;
+}
+
+/**
+ * json_gvariant_serialize:
+ * @variant: A #GVariant to convert
+ *
+ * Converts @variant to a JSON tree.
+ *
+ * Return value: (transfer full): A #JsonNode representing the root of the
+ *   JSON data structure obtained from @variant
+ *
+ * Since: 0.14
+ */
+JsonNode *
+json_gvariant_serialize (GVariant *variant)
+{
+  JsonNode *json_node = NULL;
+  GVariantClass class;
+
+  g_return_val_if_fail (variant != NULL, NULL);
+
+  class = g_variant_classify (variant);
+
+  if (! g_variant_is_container (variant))
+    {
+      json_node = json_node_new (JSON_NODE_VALUE);
+
+      switch (class)
+        {
+        case G_VARIANT_CLASS_BOOLEAN:
+          json_node_set_boolean (json_node, g_variant_get_boolean (variant));
+          break;
+
+        case G_VARIANT_CLASS_BYTE:
+          json_node_set_int (json_node, g_variant_get_byte (variant));
+          break;
+        case G_VARIANT_CLASS_INT16:
+          json_node_set_int (json_node, g_variant_get_int16 (variant));
+          break;
+        case G_VARIANT_CLASS_UINT16:
+          json_node_set_int (json_node, g_variant_get_uint16 (variant));
+          break;
+        case G_VARIANT_CLASS_INT32:
+          json_node_set_int (json_node, g_variant_get_int32 (variant));
+          break;
+        case G_VARIANT_CLASS_UINT32:
+          json_node_set_int (json_node, g_variant_get_uint32 (variant));
+          break;
+        case G_VARIANT_CLASS_INT64:
+          json_node_set_int (json_node, g_variant_get_int64 (variant));
+          break;
+        case G_VARIANT_CLASS_UINT64:
+          json_node_set_int (json_node, g_variant_get_uint64 (variant));
+          break;
+        case G_VARIANT_CLASS_HANDLE:
+          json_node_set_int (json_node, g_variant_get_handle (variant));
+          break;
+
+        case G_VARIANT_CLASS_DOUBLE:
+          json_node_set_double (json_node, g_variant_get_double (variant));
+          break;
+
+        case G_VARIANT_CLASS_STRING:
+        case G_VARIANT_CLASS_OBJECT_PATH:
+        case G_VARIANT_CLASS_SIGNATURE:
+          json_node_set_string (json_node, g_variant_get_string (variant, NULL));
+          break;
+
+        default:
+          break;
+        }
+    }
+  else
+    {
+      switch (class)
+        {
+        case G_VARIANT_CLASS_MAYBE:
+          {
+            GVariant *value;
+
+            value = g_variant_get_maybe (variant);
+            if (value == NULL)
+              {
+                json_node = json_node_new (JSON_NODE_NULL);
+              }
+            else
+              {
+                json_node = json_gvariant_serialize (value);
+                g_variant_unref (value);
+              }
+
+            break;
+          }
+
+        case G_VARIANT_CLASS_VARIANT:
+          {
+            GVariant *value;
+
+            value = g_variant_get_variant (variant);
+            json_node = json_gvariant_serialize (value);
+            g_variant_unref (value);
+
+            break;
+          }
+
+        case G_VARIANT_CLASS_ARRAY:
+          {
+            const gchar *type;
+
+            type = g_variant_get_type_string (variant);
+
+            if (type[1] == G_VARIANT_CLASS_DICT_ENTRY)
+              {
+                /* array of dictionary entries => JsonObject */
+                json_node = gvariant_to_json_object (variant);
+              }
+            else
+              {
+                /* array of anything else => JsonArray */
+                json_node = gvariant_to_json_array (variant);
+              }
+
+            break;
+          }
+
+        case G_VARIANT_CLASS_DICT_ENTRY:
+          {
+            gchar *member_name;
+            JsonObject *object;
+            JsonNode *child;
+
+            /* a single dictionary entry => JsonObject */
+            json_node = json_node_new (JSON_NODE_OBJECT);
+            object = json_object_new ();
+            json_node_set_object (json_node, object);
+            json_object_unref (object);
+
+            child = gvariant_dict_entry_to_json (variant, &member_name);
+
+            json_object_set_member (object, member_name, child);
+            g_free (member_name);
+
+            break;
+          }
+
+        case G_VARIANT_CLASS_TUPLE:
+          json_node = gvariant_to_json_array (variant);
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  return json_node;
+}
+
+/**
+ * json_gvariant_serialize_data:
+ * @variant: A #GVariant to convert
+ * @length: (out) (allow-none): Return location for the length of the returned
+ *   string, or %NULL
+ *
+ * Converts @variant to its JSON encoded string representation. This method
+ * is actually a helper function. It uses json_gvariant_serialize() to obtain the
+ * JSON tree, and then #JsonGenerator to stringify it.
+ *
+ * Return value: (transfer full): The JSON encoded string corresponding to
+ *   @variant
+ *
+ * Since: 0.14
+ */
+gchar *
+json_gvariant_serialize_data (GVariant *variant, gsize *length)
+{
+  JsonNode *json_node;
+  JsonGenerator *generator;
+  gchar *json;
+
+  json_node = json_gvariant_serialize (variant);
+
+  generator = json_generator_new ();
+
+  json_generator_set_root (generator, json_node);
+  json = json_generator_to_data (generator, length);
+
+  g_object_unref (generator);
+
+  json_node_free (json_node);
+
+  return json;
+}
+
+/* ========================================================================== */
+/* JSON to GVariant */
+/* ========================================================================== */
+
+static GVariantClass
+json_to_gvariant_get_next_class (JsonNode     *json_node,
+                                 const gchar **signature)
+{
+  if (signature == NULL)
+    {
+      GVariantClass class = 0;
+
+      switch (json_node_get_node_type (json_node))
+        {
+        case JSON_NODE_VALUE:
+          switch (json_node_get_value_type (json_node))
+            {
+            case G_TYPE_BOOLEAN:
+              class = G_VARIANT_CLASS_BOOLEAN;
+              break;
+
+            case G_TYPE_INT64:
+              class = G_VARIANT_CLASS_INT64;
+              break;
+
+            case G_TYPE_DOUBLE:
+              class = G_VARIANT_CLASS_DOUBLE;
+              break;
+
+            case G_TYPE_STRING:
+              class = G_VARIANT_CLASS_STRING;
+              break;
+            }
+
+          break;
+
+        case JSON_NODE_ARRAY:
+          class = G_VARIANT_CLASS_ARRAY;
+          break;
+
+        case JSON_NODE_OBJECT:
+          class = JSON_G_VARIANT_CLASS_DICTIONARY;
+          break;
+
+        case JSON_NODE_NULL:
+          class = G_VARIANT_CLASS_MAYBE;
+          break;
+        }
+
+      return class;
+    }
+  else
+    {
+      if ((*signature)[0] == G_VARIANT_CLASS_ARRAY &&
+          (*signature)[1] == G_VARIANT_CLASS_DICT_ENTRY)
+        return JSON_G_VARIANT_CLASS_DICTIONARY;
+      else
+        return (*signature)[0];
+    }
+}
+
+static gboolean
+json_node_assert_type (JsonNode       *json_node,
+                       JsonNodeType    type,
+                       GType           sub_type,
+                       GError        **error)
+{
+  if (JSON_NODE_TYPE (json_node) != type ||
+      (type == JSON_NODE_VALUE &&
+       (json_node_get_value_type (json_node) != sub_type)))
+    {
+      /* translators: the '%s' is the type name */
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_INVALID_DATA,
+                   _("Unexpected type '%s' in JSON node"),
+                   g_type_name (json_node_get_value_type (json_node)));
+      return FALSE;
+    }
+  else
+    {
+      return TRUE;
+    }
+}
+
+static void
+json_to_gvariant_foreach_add (gpointer data, gpointer user_data)
+{
+  GVariantBuilder *builder = (GVariantBuilder *) user_data;
+  GVariant *child = (GVariant *) data;
+
+  g_variant_builder_add_value (builder, child);
+}
+
+static void
+json_to_gvariant_foreach_free (gpointer data, gpointer user_data)
+{
+  GVariant *child = (GVariant *) data;
+
+  g_variant_unref (child);
+}
+
+static GVariant *
+json_to_gvariant_build_from_glist (GList *list, const gchar *signature)
+{
+  GVariantBuilder *builder;
+  GVariant *result;
+
+  builder = g_variant_builder_new (G_VARIANT_TYPE (signature));
+
+  g_list_foreach (list, json_to_gvariant_foreach_add, builder);
+  result = g_variant_builder_end (builder);
+
+  g_variant_builder_unref (builder);
+
+  return result;
+}
+
+static GVariant *
+json_to_gvariant_tuple (JsonNode     *json_node,
+                        const gchar **signature,
+                        GError      **error)
+{
+  GVariant *variant = NULL;
+  JsonArray *array;
+  gint i;
+  GList *children = NULL;
+  gboolean roll_back = FALSE;
+  const gchar *initial_signature;
+
+  array = json_node_get_array (json_node);
+
+  initial_signature = *signature;
+  (*signature)++;
+  i = 1;
+  while ((*signature)[0] != ')' && (*signature)[0] != '\0')
+    {
+      JsonNode *json_child;
+      GVariant *variant_child;
+
+      if (i - 1 >= json_array_get_length (array))
+        {
+          g_set_error_literal (error,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_DATA,
+                               _("Missing elements in JSON array to conform to a tuple"));
+          roll_back = TRUE;
+          break;
+        }
+
+      json_child = json_array_get_element (array, i - 1);
+
+      variant_child = json_to_gvariant_recurse (json_child, signature, error);
+      if (variant_child != NULL)
+        {
+          children = g_list_append (children, variant_child);
+        }
+      else
+        {
+          roll_back = TRUE;
+          break;
+        }
+
+      i++;
+    }
+
+  if (! roll_back)
+    {
+      if ( (*signature)[0] != ')')
+        {
+          g_set_error_literal (error,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_DATA,
+                               _("Missing closing symbol ')' in the GVariant tuple type"));
+          roll_back = TRUE;
+        }
+      else if (json_array_get_length (array) >= i)
+        {
+          g_set_error_literal (error,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_DATA,
+                               _("Unexpected extra elements in JSON array"));
+          roll_back = TRUE;
+        }
+      else
+        {
+          gchar *tuple_type;
+
+          tuple_type = g_strndup (initial_signature,
+                                  (*signature) - initial_signature + 1);
+
+          variant = json_to_gvariant_build_from_glist (children, tuple_type);
+
+          g_free (tuple_type);
+        }
+    }
+
+  if (roll_back)
+    g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
+
+  g_list_free (children);
+
+  return variant;
+}
+
+static gchar *
+signature_get_next_complete_type (const gchar **signature)
+{
+  GVariantClass class;
+  const gchar *initial_signature;
+  gchar *result;
+
+  /* here it is assumed that 'signature' is a valid type string */
+
+  initial_signature = *signature;
+  class = (*signature)[0];
+
+  if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY)
+    {
+      gchar stack[256] = {0};
+      guint stack_len = 0;
+
+      do
+        {
+          if ( (*signature)[0] == G_VARIANT_CLASS_TUPLE)
+            {
+              stack[stack_len] = ')';
+              stack_len++;
+            }
+          else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY)
+            {
+              stack[stack_len] = '}';
+              stack_len++;
+            }
+
+          (*signature)++;
+
+          if ( (*signature)[0] == stack[stack_len - 1])
+            stack_len--;
+        }
+      while (stack_len > 0);
+
+      (*signature)++;
+    }
+  else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE)
+    {
+      gchar *tmp_sig;
+
+      (*signature)++;
+      tmp_sig = signature_get_next_complete_type (signature);
+      g_free (tmp_sig);
+    }
+  else
+    {
+      (*signature)++;
+    }
+
+  result = g_strndup (initial_signature, (*signature) - initial_signature);
+
+  return result;
+}
+
+static GVariant *
+json_to_gvariant_maybe (JsonNode     *json_node,
+                        const gchar **signature,
+                        GError      **error)
+{
+  GVariant *variant = NULL;
+  GVariant *value;
+  gchar *maybe_signature;
+
+  if (signature)
+    {
+      (*signature)++;
+      maybe_signature = signature_get_next_complete_type (signature);
+    }
+  else
+    {
+      maybe_signature = g_strdup ("v");
+    }
+
+  if (json_node_get_node_type (json_node) == JSON_NODE_NULL)
+    {
+      variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), NULL);
+    }
+  else
+    {
+      const gchar *tmp_signature;
+
+      tmp_signature = maybe_signature;
+      value = json_to_gvariant_recurse (json_node,
+                                        &tmp_signature,
+                                        error);
+
+      if (value != NULL)
+        variant = g_variant_new_maybe (G_VARIANT_TYPE (maybe_signature), value);
+    }
+
+  g_free (maybe_signature);
+
+  /* compensate the (*signature)++ call at the end of 'recurse()' */
+  if (signature)
+    (*signature)--;
+
+  return variant;
+}
+
+static GVariant *
+json_to_gvariant_array (JsonNode     *json_node,
+                        const gchar **signature,
+                        GError      **error)
+{
+  GVariant *variant = NULL;
+  JsonArray *array;
+  GList *children = NULL;
+  gboolean roll_back = FALSE;
+  const gchar *orig_signature;
+  gchar *child_signature;
+
+  array = json_node_get_array (json_node);
+
+  if (signature != NULL)
+    {
+      orig_signature = *signature;
+
+      (*signature)++;
+      child_signature = signature_get_next_complete_type (signature);
+    }
+  else
+    child_signature = g_strdup ("v");
+
+  if (json_array_get_length (array) > 0)
+    {
+      gint i;
+      guint len;
+
+      len = json_array_get_length (array);
+      for (i = 0; i < len; i++)
+        {
+          JsonNode *json_child;
+          GVariant *variant_child;
+          const gchar *tmp_signature;
+
+          json_child = json_array_get_element (array, i);
+
+          tmp_signature = child_signature;
+          variant_child = json_to_gvariant_recurse (json_child,
+                                                    &tmp_signature,
+                                                    error);
+          if (variant_child != NULL)
+            {
+              children = g_list_append (children, variant_child);
+            }
+          else
+            {
+              roll_back = TRUE;
+              break;
+            }
+        }
+    }
+
+  if (!roll_back)
+    {
+      gchar *array_signature;
+
+      if (signature)
+        array_signature = g_strndup (orig_signature, (*signature) - orig_signature);
+      else
+        array_signature = g_strdup ("av");
+
+      variant = json_to_gvariant_build_from_glist (children, array_signature);
+
+      g_free (array_signature);
+
+      /* compensate the (*signature)++ call at the end of 'recurse()' */
+      if (signature)
+        (*signature)--;
+    }
+  else
+    g_list_foreach (children, json_to_gvariant_foreach_free, NULL);
+
+  g_list_free (children);
+  g_free (child_signature);
+
+  return variant;
+}
+
+static GVariant *
+gvariant_simple_from_string (const gchar    *st,
+                             GVariantClass   class,
+                             GError        **error)
+{
+  GVariant *variant = NULL;
+  gchar *nptr = NULL;
+
+  errno = 0;
+
+  switch (class)
+    {
+    case G_VARIANT_CLASS_BOOLEAN:
+      if (g_strcmp0 (st, "true") == 0)
+        variant = g_variant_new_boolean (TRUE);
+      else if (g_strcmp0 (st, "false") == 0)
+        variant = g_variant_new_boolean (FALSE);
+      else
+        errno = 1;
+      break;
+
+    case G_VARIANT_CLASS_BYTE:
+      variant = g_variant_new_byte (g_ascii_strtoll (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_INT16:
+      variant = g_variant_new_int16 (g_ascii_strtoll (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_UINT16:
+      variant = g_variant_new_uint16 (g_ascii_strtoll (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_INT32:
+      variant = g_variant_new_int32 (g_ascii_strtoll (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_UINT32:
+      variant = g_variant_new_uint32 (g_ascii_strtoull (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_INT64:
+      variant = g_variant_new_int64 (g_ascii_strtoll (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_UINT64:
+      variant = g_variant_new_uint64 (g_ascii_strtoull (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_HANDLE:
+      variant = g_variant_new_handle (strtol (st, &nptr, 10));
+      break;
+
+    case G_VARIANT_CLASS_DOUBLE:
+      variant = g_variant_new_double (g_ascii_strtod (st, &nptr));
+      break;
+
+    case G_VARIANT_CLASS_STRING:
+    case G_VARIANT_CLASS_OBJECT_PATH:
+    case G_VARIANT_CLASS_SIGNATURE:
+      variant = g_variant_new_string (st);
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (errno != 0 || nptr == st)
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_INVALID_DATA,
+                           _("Invalid string value converting to GVariant"));
+      if (variant != NULL)
+        {
+          g_variant_unref (variant);
+          variant = NULL;
+        }
+    }
+
+  return variant;
+}
+
+static void
+parse_dict_entry_signature (const gchar **signature,
+                            gchar       **entry_signature,
+                            gchar       **key_signature,
+                            gchar       **value_signature)
+{
+  const gchar *tmp_sig;
+
+  if (signature != NULL)
+    *entry_signature = signature_get_next_complete_type (signature);
+  else
+    *entry_signature = g_strdup ("{sv}");
+
+  tmp_sig = (*entry_signature) + 1;
+  *key_signature = signature_get_next_complete_type (&tmp_sig);
+  *value_signature = signature_get_next_complete_type (&tmp_sig);
+}
+
+static GVariant *
+json_to_gvariant_dict_entry (JsonNode     *json_node,
+                             const gchar **signature,
+                             GError      **error)
+{
+  GVariant *variant = NULL;
+  JsonObject *obj;
+
+  gchar *entry_signature;
+  gchar *key_signature;
+  gchar *value_signature;
+  const gchar *tmp_signature;
+
+  GList *member;
+
+  const gchar *json_member;
+  JsonNode *json_value;
+  GVariant *variant_member;
+  GVariant *variant_value;
+
+  obj = json_node_get_object (json_node);
+
+  if (json_object_get_size (obj) != 1)
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_INVALID_DATA,
+                           _("A GVariant dictionary entry expects a JSON object with exactly one member"));
+      return NULL;
+    }
+
+  parse_dict_entry_signature (signature,
+                              &entry_signature,
+                              &key_signature,
+                              &value_signature);
+
+  member = json_object_get_members (obj);
+
+  json_member = (const gchar *) member->data;
+  variant_member = gvariant_simple_from_string (json_member,
+                                                key_signature[0],
+                                                error);
+  if (variant_member != NULL)
+    {
+      json_value = json_object_get_member (obj, json_member);
+
+      tmp_signature = value_signature;
+      variant_value = json_to_gvariant_recurse (json_value,
+                                                &tmp_signature,
+                                                error);
+
+      if (variant_value != NULL)
+        {
+          GVariantBuilder *builder;
+
+          builder = g_variant_builder_new (G_VARIANT_TYPE (entry_signature));
+          g_variant_builder_add_value (builder, variant_member);
+          g_variant_builder_add_value (builder, variant_value);
+          variant = g_variant_builder_end (builder);
+
+          g_variant_builder_unref (builder);
+        }
+    }
+
+  g_list_free (member);
+  g_free (value_signature);
+  g_free (key_signature);
+  g_free (entry_signature);
+
+  /* compensate the (*signature)++ call at the end of 'recurse()' */
+  if (signature)
+    (*signature)--;
+
+  return variant;
+}
+
+static GVariant *
+json_to_gvariant_dictionary (JsonNode     *json_node,
+                             const gchar **signature,
+                             GError      **error)
+{
+  GVariant *variant = NULL;
+  JsonObject *obj;
+  gboolean roll_back = FALSE;
+
+  gchar *dict_signature;
+  gchar *entry_signature;
+  gchar *key_signature;
+  gchar *value_signature;
+  const gchar *tmp_signature;
+
+  GVariantBuilder *builder;
+  GList *members;
+  GList *member;
+
+  obj = json_node_get_object (json_node);
+
+  if (signature != NULL)
+    (*signature)++;
+
+  parse_dict_entry_signature (signature,
+                              &entry_signature,
+                              &key_signature,
+                              &value_signature);
+
+  dict_signature = g_strdup_printf ("a%s", entry_signature);
+
+  builder = g_variant_builder_new (G_VARIANT_TYPE (dict_signature));
+
+  members = json_object_get_members (obj);
+
+  member = members;
+  while (member != NULL)
+    {
+      const gchar *json_member;
+      JsonNode *json_value;
+      GVariant *variant_member;
+      GVariant *variant_value;
+
+      json_member = (const gchar *) member->data;
+      variant_member = gvariant_simple_from_string (json_member,
+                                                    key_signature[0],
+                                                    error);
+      if (variant_member == NULL)
+        {
+          roll_back = TRUE;
+          break;
+        }
+
+      json_value = json_object_get_member (obj, json_member);
+
+      tmp_signature = value_signature;
+      variant_value = json_to_gvariant_recurse (json_value,
+                                                &tmp_signature,
+                                                error);
+
+      if (variant_value != NULL)
+        {
+          g_variant_builder_open (builder, G_VARIANT_TYPE (entry_signature));
+          g_variant_builder_add_value (builder, variant_member);
+          g_variant_builder_add_value (builder, variant_value);
+          g_variant_builder_close (builder);
+        }
+      else
+        {
+          roll_back = TRUE;
+          break;
+        }
+
+      member = member->next;
+    }
+
+  if (! roll_back)
+    variant = g_variant_builder_end (builder);
+
+  g_variant_builder_unref (builder);
+  g_list_free (members);
+  g_free (value_signature);
+  g_free (key_signature);
+  g_free (entry_signature);
+  g_free (dict_signature);
+
+  /* compensate the (*signature)++ call at the end of 'recurse()' */
+  if (signature != NULL)
+    (*signature)--;
+
+  return variant;
+}
+
+static GVariant *
+json_to_gvariant_recurse (JsonNode      *json_node,
+                          const gchar  **signature,
+                          GError       **error)
+{
+  GVariant *variant = NULL;
+  GVariantClass class;
+
+  class = json_to_gvariant_get_next_class (json_node, signature);
+
+  if (class == JSON_G_VARIANT_CLASS_DICTIONARY)
+    {
+      if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
+        variant = json_to_gvariant_dictionary (json_node, signature, error);
+
+      goto out;
+    }
+
+  switch (class)
+    {
+    case G_VARIANT_CLASS_BOOLEAN:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_BOOLEAN, error))
+        variant = g_variant_new_boolean (json_node_get_boolean (json_node));
+      break;
+
+    case G_VARIANT_CLASS_BYTE:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_byte (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_INT16:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_int16 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_UINT16:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_uint16 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_INT32:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_int32 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_UINT32:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_uint32 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_INT64:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_int64 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_UINT64:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_uint64 (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_HANDLE:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_INT64, error))
+        variant = g_variant_new_handle (json_node_get_int (json_node));
+      break;
+
+    case G_VARIANT_CLASS_DOUBLE:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_DOUBLE, error))
+        variant = g_variant_new_double (json_node_get_double (json_node));
+      break;
+
+    case G_VARIANT_CLASS_STRING:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
+        variant = g_variant_new_string (json_node_get_string (json_node));
+      break;
+
+    case G_VARIANT_CLASS_OBJECT_PATH:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
+        variant = g_variant_new_object_path (json_node_get_string (json_node));
+      break;
+
+    case G_VARIANT_CLASS_SIGNATURE:
+      if (json_node_assert_type (json_node, JSON_NODE_VALUE, G_TYPE_STRING, error))
+        variant = g_variant_new_signature (json_node_get_string (json_node));
+      break;
+
+    case G_VARIANT_CLASS_VARIANT:
+      variant = g_variant_new_variant (json_to_gvariant_recurse (json_node,
+                                                                 NULL,
+                                                                 error));
+      break;
+
+    case G_VARIANT_CLASS_MAYBE:
+      variant = json_to_gvariant_maybe (json_node, signature, error);
+      break;
+
+    case G_VARIANT_CLASS_ARRAY:
+      if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
+        variant = json_to_gvariant_array (json_node, signature, error);
+      break;
+
+    case G_VARIANT_CLASS_TUPLE:
+      if (json_node_assert_type (json_node, JSON_NODE_ARRAY, 0, error))
+        variant = json_to_gvariant_tuple (json_node, signature, error);
+      break;
+
+    case G_VARIANT_CLASS_DICT_ENTRY:
+      if (json_node_assert_type (json_node, JSON_NODE_OBJECT, 0, error))
+        variant = json_to_gvariant_dict_entry (json_node, signature, error);
+      break;
+
+    default:
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_INVALID_DATA,
+                   _("GVariant class '%c' not supported"), class);
+      break;
+    }
+
+out:
+  if (signature)
+    (*signature)++;
+
+  return variant;
+}
+
+/**
+ * json_gvariant_deserialize:
+ * @json_node: A #JsonNode to convert
+ * @signature: (allow-none): A valid #GVariant type string, or %NULL
+ * @error: A pointer to a #GError
+ *
+ * Converts a JSON data structure to a GVariant value using @signature to
+ * resolve ambiguous data types. If no error occurs, the resulting #GVariant
+ * is guaranteed to conform to @signature.
+ *
+ * If @signature is not %NULL but does not represent a valid GVariant type
+ * string, %NULL is returned and error is set to %G_IO_ERROR_INVALID_ARGUMENT.
+ * If a @signature is provided but the JSON structure cannot be mapped to it,
+ * %NULL is returned and error is set to %G_IO_ERROR_INVALID_DATA.
+ * If @signature is %NULL, the conversion is done based strictly on the types
+ * in the JSON nodes.
+ *
+ * Return value: (transfer full): A newly created #GVariant compliant with
+ *   @signature, or %NULL on error
+ *
+ * Since: 0.14
+ */
+GVariant *
+json_gvariant_deserialize (JsonNode     *json_node,
+                           const gchar  *signature,
+                           GError      **error)
+{
+  g_return_val_if_fail (json_node != NULL, NULL);
+
+  if (signature != NULL && ! g_variant_type_string_is_valid (signature))
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_INVALID_ARGUMENT,
+                           _("Invalid GVariant signature"));
+      return NULL;
+    }
+
+  return json_to_gvariant_recurse (json_node, signature ? &signature : NULL, error);
+}
+
+/**
+ * json_gvariant_deserialize_data:
+ * @json: A JSON data string
+ * @length: The length of @json, or -1 if %NULL-terminated
+ * @signature: (allow-none): A valid #GVariant type string, or %NULL
+ * @error: A pointer to a #GError
+ *
+ * Converts a JSON string to a #GVariant value. This method works exactly
+ * like json_gvariant_deserialize(), but takes a JSON encoded string instead.
+ * The string is first converted to a #JsonNode using #JsonParser, and then
+ * json_gvariant_deserialize() is called.
+ *
+ * Returns: (transfer full): A newly created #GVariant compliant with
+ *   @signature, or %NULL on error
+ *
+ * Since: 0.14
+ */
+GVariant *
+json_gvariant_deserialize_data (const gchar  *json,
+                                gssize        length,
+                                const gchar  *signature,
+                                GError      **error)
+{
+  JsonParser *parser;
+  GVariant *variant = NULL;
+  JsonNode *root;
+
+  parser = json_parser_new ();
+
+  if (! json_parser_load_from_data (parser, json, length, error))
+    return NULL;
+
+  root = json_parser_get_root (parser);
+  if (root == NULL)
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR,
+                           G_IO_ERROR_INVALID_DATA,
+                           _("JSON data is empty"));
+    }
+  else
+    {
+      variant =
+        json_gvariant_deserialize (json_parser_get_root (parser), signature, error);
+    }
+
+  g_object_unref (parser);
+
+  return variant;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-gvariant.h b/src/glib-jsonrpc/json-glib/json-gvariant.h
new file mode 100644
index 0000000..6644b21
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-gvariant.h
@@ -0,0 +1,46 @@
+/* json-gvariant.h - JSON GVariant integration
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Eduardo Lima Mitev  <elima igalia com>
+ */
+
+#ifndef __JSON_GVARIANT_H__
+#define __JSON_GVARIANT_H__
+
+#include <glib.h>
+#include <json-glib/json-glib.h>
+
+G_BEGIN_DECLS
+
+JsonNode * json_gvariant_serialize        (GVariant *variant);
+gchar *    json_gvariant_serialize_data   (GVariant *variant,
+                                           gsize    *length);
+
+GVariant * json_gvariant_deserialize      (JsonNode     *json_node,
+                                           const gchar  *signature,
+                                           GError      **error);
+GVariant * json_gvariant_deserialize_data (const gchar  *json,
+                                           gssize        length,
+                                           const gchar  *signature,
+                                           GError      **error);
+
+G_END_DECLS
+
+#endif /* __JSON_GVARIANT_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-marshal.c b/src/glib-jsonrpc/json-glib/json-marshal.c
new file mode 100644
index 0000000..dae8b56
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-marshal.c
@@ -0,0 +1,132 @@
+#include "json-marshal.h"
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:VOID (./json-marshal.list:1) */
+
+/* VOID:BOXED (./json-marshal.list:2) */
+
+/* VOID:BOXED,STRING (./json-marshal.list:3) */
+void
+_json_marshal_VOID__BOXED_STRING (GClosure     *closure,
+                                  GValue       *return_value G_GNUC_UNUSED,
+                                  guint         n_param_values,
+                                  const GValue *param_values,
+                                  gpointer      invocation_hint G_GNUC_UNUSED,
+                                  gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__BOXED_STRING) (gpointer     data1,
+                                                   gpointer     arg_1,
+                                                   gpointer     arg_2,
+                                                   gpointer     data2);
+  register GMarshalFunc_VOID__BOXED_STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__BOXED_STRING) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_boxed (param_values + 1),
+            g_marshal_value_peek_string (param_values + 2),
+            data2);
+}
+
+/* VOID:BOXED,INT (./json-marshal.list:4) */
+void
+_json_marshal_VOID__BOXED_INT (GClosure     *closure,
+                               GValue       *return_value G_GNUC_UNUSED,
+                               guint         n_param_values,
+                               const GValue *param_values,
+                               gpointer      invocation_hint G_GNUC_UNUSED,
+                               gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__BOXED_INT) (gpointer     data1,
+                                                gpointer     arg_1,
+                                                gint         arg_2,
+                                                gpointer     data2);
+  register GMarshalFunc_VOID__BOXED_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__BOXED_INT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_boxed (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            data2);
+}
+
+/* VOID:POINTER (./json-marshal.list:5) */
+
diff --git a/src/glib-jsonrpc/json-glib/json-marshal.h b/src/glib-jsonrpc/json-glib/json-marshal.h
new file mode 100644
index 0000000..f4f7658
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-marshal.h
@@ -0,0 +1,37 @@
+
+#ifndef ___json_marshal_MARSHAL_H__
+#define ___json_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:VOID (./json-marshal.list:1) */
+#define _json_marshal_VOID__VOID	g_cclosure_marshal_VOID__VOID
+
+/* VOID:BOXED (./json-marshal.list:2) */
+#define _json_marshal_VOID__BOXED	g_cclosure_marshal_VOID__BOXED
+
+/* VOID:BOXED,STRING (./json-marshal.list:3) */
+extern void _json_marshal_VOID__BOXED_STRING (GClosure     *closure,
+                                              GValue       *return_value,
+                                              guint         n_param_values,
+                                              const GValue *param_values,
+                                              gpointer      invocation_hint,
+                                              gpointer      marshal_data);
+
+/* VOID:BOXED,INT (./json-marshal.list:4) */
+extern void _json_marshal_VOID__BOXED_INT (GClosure     *closure,
+                                           GValue       *return_value,
+                                           guint         n_param_values,
+                                           const GValue *param_values,
+                                           gpointer      invocation_hint,
+                                           gpointer      marshal_data);
+
+/* VOID:POINTER (./json-marshal.list:5) */
+#define _json_marshal_VOID__POINTER	g_cclosure_marshal_VOID__POINTER
+
+G_END_DECLS
+
+#endif /* ___json_marshal_MARSHAL_H__ */
+
diff --git a/src/glib-jsonrpc/json-glib/json-node.c b/src/glib-jsonrpc/json-glib/json-node.c
new file mode 100644
index 0000000..67cdc95
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-node.c
@@ -0,0 +1,800 @@
+/* json-node.c - JSON object model node
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include "json-types-private.h"
+
+/**
+ * SECTION:json-node
+ * @short_description: Node in a JSON object model
+ *
+ * A #JsonNode is a generic container of elements inside a JSON stream.
+ * It can contain fundamental types (integers, booleans, floating point
+ * numbers, strings) and complex types (arrays and objects).
+ *
+ * When parsing a JSON data stream you extract the root node and walk
+ * the node tree by retrieving the type of data contained inside the
+ * node with the %JSON_NODE_TYPE macro. If the node contains a fundamental
+ * type you can retrieve a copy of the #GValue holding it with the
+ * json_node_get_value() function, and then use the #GValue API to extract
+ * the data; if the node contains a complex type you can retrieve the
+ * #JsonObject or the #JsonArray using json_node_get_object() or
+ * json_node_get_array() respectively, and then retrieve the nodes
+ * they contain.
+ */
+
+G_DEFINE_BOXED_TYPE (JsonNode, json_node, json_node_copy, json_node_free);
+
+/**
+ * json_node_get_value_type:
+ * @node: a #JsonNode
+ *
+ * Returns the #GType of the payload of the node.
+ *
+ * Return value: a #GType for the payload.
+ *
+ * Since: 0.4
+ */
+GType
+json_node_get_value_type (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, G_TYPE_INVALID);
+
+  switch (node->type)
+    {
+    case JSON_NODE_OBJECT:
+      return JSON_TYPE_OBJECT;
+
+    case JSON_NODE_ARRAY:
+      return JSON_TYPE_ARRAY;
+
+    case JSON_NODE_NULL:
+      return G_TYPE_INVALID;
+
+    case JSON_NODE_VALUE:
+      return G_VALUE_TYPE (&(node->data.value));
+
+    default:
+      g_assert_not_reached ();
+      return G_TYPE_INVALID;
+    }
+}
+
+/**
+ * json_node_new:
+ * @type: a #JsonNodeType
+ *
+ * Creates a new #JsonNode of @type.
+ *
+ * Return value: the newly created #JsonNode
+ */
+JsonNode *
+json_node_new (JsonNodeType type)
+{
+  JsonNode *data;
+
+  g_return_val_if_fail (type >= JSON_NODE_OBJECT &&
+                        type <= JSON_NODE_NULL, NULL);
+
+  data = g_slice_new0 (JsonNode);
+  data->type = type;
+
+  return data;
+}
+
+/**
+ * json_node_copy:
+ * @node: a #JsonNode
+ *
+ * Copies @node. If the node contains complex data types then the reference
+ * count of the objects is increased.
+ *
+ * Return value: (transfer full): the copied #JsonNode
+ */
+JsonNode *
+json_node_copy (JsonNode *node)
+{
+  JsonNode *copy;
+
+  g_return_val_if_fail (node != NULL, NULL);
+
+  copy = g_slice_new0 (JsonNode);
+  copy->type = node->type;
+
+  switch (copy->type)
+    {
+    case JSON_NODE_OBJECT:
+      if (node->data.object)
+        copy->data.object = json_object_ref (node->data.object);
+      break;
+
+    case JSON_NODE_ARRAY:
+      if (node->data.array)
+        copy->data.array = json_array_ref (node->data.array);
+      break;
+
+    case JSON_NODE_VALUE:
+      if (G_VALUE_TYPE (&(node->data.value)) != G_TYPE_INVALID)
+        {
+          g_value_init (&(copy->data.value), G_VALUE_TYPE (&(node->data.value)));
+          g_value_copy (&(node->data.value), &(copy->data.value));
+        }
+      break;
+
+    case JSON_NODE_NULL:
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return copy;
+}
+
+/**
+ * json_node_set_object:
+ * @node: a #JsonNode
+ * @object: a #JsonObject
+ *
+ * Sets @objects inside @node. The reference count of @object is increased.
+ */
+void
+json_node_set_object (JsonNode   *node,
+                      JsonObject *object)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
+
+  if (node->data.object)
+    json_object_unref (node->data.object);
+
+  if (object)
+    node->data.object = json_object_ref (object);
+  else
+    node->data.object = NULL;
+}
+
+/**
+ * json_node_take_object:
+ * @node: a #JsonNode
+ * @object: (transfer full): a #JsonObject
+ *
+ * Sets @object inside @node. The reference count of @object is not increased.
+ */
+void
+json_node_take_object (JsonNode   *node,
+                       JsonObject *object)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT);
+
+  if (node->data.object)
+    {
+      json_object_unref (node->data.object);
+      node->data.object = NULL;
+    }
+
+  if (object)
+    node->data.object = object;
+}
+
+/**
+ * json_node_get_object:
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonObject stored inside a #JsonNode
+ *
+ * Return value: (transfer none): the #JsonObject
+ */
+JsonObject *
+json_node_get_object (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
+
+  return node->data.object;
+}
+
+/**
+ * json_node_dup_object:
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonObject inside @node. The reference count of
+ * the returned object is increased.
+ *
+ * Return value: (transfer full): the #JsonObject
+ */
+JsonObject *
+json_node_dup_object (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL);
+
+  if (node->data.object)
+    return json_object_ref (node->data.object);
+  
+  return NULL;
+}
+
+/**
+ * json_node_set_array:
+ * @node: a #JsonNode
+ * @array: a #JsonArray
+ *
+ * Sets @array inside @node and increases the #JsonArray reference count
+ */
+void
+json_node_set_array (JsonNode  *node,
+                     JsonArray *array)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
+
+  if (node->data.array)
+    json_array_unref (node->data.array);
+
+  if (array)
+    node->data.array = json_array_ref (array);
+  else
+    node->data.array = NULL;
+}
+
+/**
+ * json_node_take_array:
+ * @node: a #JsonNode
+ * @array: (transfer full): a #JsonArray
+ *
+ * Sets @array into @node without increasing the #JsonArray reference count.
+ */
+void
+json_node_take_array (JsonNode  *node,
+                      JsonArray *array)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY);
+
+  if (node->data.array)
+    {
+      json_array_unref (node->data.array);
+      node->data.array = NULL;
+    }
+
+  if (array)
+    node->data.array = array;
+}
+
+/**
+ * json_node_get_array:
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonArray stored inside a #JsonNode
+ *
+ * Return value: (transfer none): the #JsonArray
+ */
+JsonArray *
+json_node_get_array (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
+
+  return node->data.array;
+}
+
+/**
+ * json_node_dup_array
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonArray stored inside a #JsonNode and returns it
+ * with its reference count increased by one.
+ *
+ * Return value: (transfer full): the #JsonArray with its reference
+ *   count increased.
+ */
+JsonArray *
+json_node_dup_array (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY, NULL);
+
+  if (node->data.array)
+    return json_array_ref (node->data.array);
+
+  return NULL;
+}
+
+/**
+ * json_node_get_value:
+ * @node: a #JsonNode
+ * @value: (out caller-allocates): return location for an uninitialized value
+ *
+ * Retrieves a value from a #JsonNode and copies into @value. When done
+ * using it, call g_value_unset() on the #GValue.
+ */
+void
+json_node_get_value (JsonNode *node,
+                     GValue   *value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+
+  if (G_VALUE_TYPE (&(node->data.value)) != G_TYPE_INVALID)
+    {
+      g_value_init (value, G_VALUE_TYPE (&(node->data.value)));
+      g_value_copy (&(node->data.value), value);
+    }
+}
+
+static void inline
+node_value_unset (JsonNode *node)
+{
+  if (G_VALUE_TYPE (&(node->data.value)) != G_TYPE_INVALID)
+    g_value_unset (&(node->data.value));
+}
+
+/**
+ * json_node_set_value:
+ * @node: a #JsonNode
+ * @value: the #GValue to set
+ *
+ * Sets @value inside @node. The passed #GValue is copied into the #JsonNode
+ */
+void
+json_node_set_value (JsonNode     *node,
+                     const GValue *value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+  g_return_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID);
+
+  switch (G_VALUE_TYPE (value))
+    {
+    /* direct copy for the types we use */
+    case G_TYPE_INT64:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_DOUBLE:
+    case G_TYPE_STRING:
+      node_value_unset (node);
+      g_value_init (&(node->data.value), G_VALUE_TYPE (value));
+      g_value_copy (value, &(node->data.value));
+      break;
+
+    /* auto-promote ints to long longs */
+    case G_TYPE_INT:
+      node_value_unset (node);
+      g_value_init (&(node->data.value), G_TYPE_INT64);
+      g_value_set_int64 (&(node->data.value),
+                         g_value_get_int (value));
+      break;
+
+    /* auto-promote single precision to double precision */
+    case G_TYPE_FLOAT:
+      node_value_unset (node);
+      g_value_init (&(node->data.value), G_TYPE_DOUBLE);
+      g_value_set_double (&(node->data.value),
+                          g_value_get_float (value));
+      break;
+
+    default:
+      g_warning ("Invalid value of type '%s'",
+                 g_type_name (G_VALUE_TYPE (value)));
+      return;
+    }
+
+}
+
+/**
+ * json_node_free:
+ * @node: a #JsonNode
+ *
+ * Frees the resources allocated by @node.
+ */
+void
+json_node_free (JsonNode *node)
+{
+  if (G_LIKELY (node))
+    {
+      switch (node->type)
+        {
+        case JSON_NODE_OBJECT:
+          if (node->data.object)
+            json_object_unref (node->data.object);
+          break;
+
+        case JSON_NODE_ARRAY:
+          if (node->data.array)
+            json_array_unref (node->data.array);
+          break;
+
+        case JSON_NODE_VALUE:
+          g_value_unset (&(node->data.value));
+          break;
+
+        case JSON_NODE_NULL:
+          break;
+        }
+
+      g_slice_free (JsonNode, node);
+    }
+}
+
+/**
+ * json_node_type_name:
+ * @node: a #JsonNode
+ *
+ * Retrieves the user readable name of the data type contained by @node.
+ *
+ * Return value: a string containing the name of the type. The returned string
+ *   is owned by the node and should never be modified or freed
+ */
+const gchar *
+json_node_type_name (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, "(null)");
+
+  switch (node->type)
+    {
+    case JSON_NODE_OBJECT:
+    case JSON_NODE_ARRAY:
+    case JSON_NODE_NULL:
+      return json_node_type_get_name (node->type);
+
+    case JSON_NODE_VALUE:
+      return g_type_name (G_VALUE_TYPE (&(node->data.value)));
+    }
+
+  return "unknown";
+}
+
+const gchar *
+json_node_type_get_name (JsonNodeType node_type)
+{
+  switch (node_type)
+    {
+    case JSON_NODE_OBJECT:
+      return "JsonObject";
+
+    case JSON_NODE_ARRAY:
+      return "JsonArray";
+
+    case JSON_NODE_NULL:
+      return "NULL";
+
+    case JSON_NODE_VALUE:
+      return "Value";
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return "unknown";
+}
+
+/**
+ * json_node_set_parent:
+ * @node: a #JsonNode
+ * @parent: (transfer none): the parent #JsonNode of @node
+ *
+ * Sets the parent #JsonNode of @node
+ *
+ * Since: 0.8
+ */
+void
+json_node_set_parent (JsonNode *node,
+                      JsonNode *parent)
+{
+  g_return_if_fail (node != NULL);
+
+  node->parent = parent;
+}
+
+/**
+ * json_node_get_parent:
+ * @node: a #JsonNode
+ *
+ * Retrieves the parent #JsonNode of @node.
+ *
+ * Return value: (transfer none): the parent node, or %NULL if @node is
+ *   the root node
+ */
+JsonNode *
+json_node_get_parent (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+
+  return node->parent;
+}
+
+/**
+ * json_node_set_string:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ * @value: a string value
+ *
+ * Sets @value as the string content of the @node, replacing any existing
+ * content.
+ */
+void
+json_node_set_string (JsonNode    *node,
+                      const gchar *value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
+    g_value_set_string (&(node->data.value), value);
+  else
+    {
+      GValue copy = { 0, };
+
+      g_value_init (&copy, G_TYPE_STRING);
+      g_value_set_string (&copy, value);
+
+      json_node_set_value (node, &copy);
+
+      g_value_unset (&copy);
+    }
+}
+
+/**
+ * json_node_get_string:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets the string value stored inside a #JsonNode
+ *
+ * Return value: a string value.
+ */
+const gchar *
+json_node_get_string (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return NULL;
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
+    return g_value_get_string (&(node->data.value));
+
+  return NULL;
+}
+
+/**
+ * json_node_dup_string:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets a copy of the string value stored inside a #JsonNode
+ *
+ * Return value: (transfer full): a newly allocated string containing a copy
+ *   of the #JsonNode contents. Use g_free() to free the allocated resources
+ */
+gchar *
+json_node_dup_string (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return NULL;
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_STRING)
+    return g_value_dup_string (&(node->data.value));
+
+  return NULL;
+}
+
+/**
+ * json_node_set_int:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ * @value: an integer value
+ *
+ * Sets @value as the integer content of the @node, replacing any existing
+ * content.
+ */
+void
+json_node_set_int (JsonNode *node,
+                   gint64    value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_INT64)
+    g_value_set_int64 (&(node->data.value), value);
+  else
+    {
+      GValue copy = { 0, };
+
+      g_value_init (&copy, G_TYPE_INT64);
+      g_value_set_int64 (&copy, value);
+
+      json_node_set_value (node, &copy);
+
+      g_value_unset (&copy);
+    }
+}
+
+/**
+ * json_node_get_int:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets the integer value stored inside a #JsonNode
+ *
+ * Return value: an integer value.
+ */
+gint64
+json_node_get_int (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, 0);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return 0;
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_INT64)
+    return g_value_get_int64 (&(node->data.value));
+
+  return 0;
+}
+
+/**
+ * json_node_set_double:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ * @value: a double value
+ *
+ * Sets @value as the double content of the @node, replacing any existing
+ * content.
+ */
+void
+json_node_set_double (JsonNode *node,
+                      gdouble   value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_DOUBLE)
+    g_value_set_double (&(node->data.value), value);
+  else
+    {
+      GValue copy = { 0, };
+
+      g_value_init (&copy, G_TYPE_DOUBLE);
+      g_value_set_double (&copy, value);
+
+      json_node_set_value (node, &copy);
+
+      g_value_unset (&copy);
+    }
+}
+
+/**
+ * json_node_get_double:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets the double value stored inside a #JsonNode
+ *
+ * Return value: a double value.
+ */
+gdouble
+json_node_get_double (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, 0.0);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return 0;
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_DOUBLE)
+    return g_value_get_double (&(node->data.value));
+
+  return 0.0;
+}
+
+/**
+ * json_node_set_boolean:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ * @value: a boolean value
+ *
+ * Sets @value as the boolean content of the @node, replacing any existing
+ * content.
+ */
+void
+json_node_set_boolean (JsonNode *node,
+                       gboolean  value)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE);
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_BOOLEAN)
+    g_value_set_boolean (&(node->data.value), value);
+  else
+    {
+      GValue copy = { 0, };
+
+      g_value_init (&copy, G_TYPE_BOOLEAN);
+      g_value_set_boolean (&copy, value);
+
+      json_node_set_value (node, &copy);
+
+      g_value_unset (&copy);
+    }
+}
+
+/**
+ * json_node_get_boolean:
+ * @node: a #JsonNode of type %JSON_NODE_VALUE
+ *
+ * Gets the boolean value stored inside a #JsonNode
+ *
+ * Return value: a boolean value.
+ */
+gboolean
+json_node_get_boolean (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  if (JSON_NODE_TYPE (node) == JSON_NODE_NULL)
+    return FALSE;
+
+  if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_BOOLEAN)
+    return g_value_get_boolean (&(node->data.value));
+
+  return FALSE;
+}
+
+/**
+ * json_node_get_node_type:
+ * @node: a #JsonNode
+ *
+ * Retrieves the #JsonNodeType of @node
+ *
+ * Return value: the type of the node
+ *
+ * Since: 0.8
+ */
+JsonNodeType
+json_node_get_node_type (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, JSON_NODE_NULL);
+
+  return node->type;
+}
+
+/**
+ * json_node_is_null:
+ * @node: a #JsonNode
+ *
+ * Checks whether @node is a %JSON_NODE_NULL
+ *
+ * <note>A null node is not the same as a %NULL #JsonNode</note>
+ *
+ * Return value: %TRUE if the node is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_node_is_null (JsonNode *node)
+{
+  g_return_val_if_fail (node != NULL, TRUE);
+
+  return node->type == JSON_NODE_NULL;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-object.c b/src/glib-jsonrpc/json-glib/json-object.c
new file mode 100644
index 0000000..9c6d585
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-object.c
@@ -0,0 +1,856 @@
+/* json-object.c - JSON object implementation
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "json-types-private.h"
+
+/**
+ * SECTION:json-object
+ * @short_description: a JSON object representation
+ *
+ * #JsonArray is the representation of the object type inside JSON. It contains
+ * #JsonNode<!-- -->s, which may contain fundamental types, arrays or other
+ * objects. Each member of an object is accessed using its name.
+ *
+ * Since objects can be expensive, they are reference counted. You can control
+ * the lifetime of a #JsonObject using json_object_ref() and json_object_unref().
+ *
+ * To add or overwrite a member with a given name, use json_object_set_member().
+ * To extract a member with a given name, use json_object_get_member().
+ * To retrieve the list of members, use json_object_get_members().
+ * To retrieve the size of the object (that is, the number of members it has),
+ * use json_object_get_size().
+ */
+
+G_DEFINE_BOXED_TYPE (JsonObject, json_object, json_object_ref, json_object_unref);
+
+/**
+ * json_object_new:
+ * 
+ * Creates a new #JsonObject, an JSON object type representation.
+ *
+ * Return value: the newly created #JsonObject
+ */
+JsonObject *
+json_object_new (void)
+{
+  JsonObject *object;
+
+  object = g_slice_new (JsonObject);
+  
+  object->ref_count = 1;
+  object->members = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify) json_node_free);
+  object->members_ordered = NULL;
+
+  return object;
+}
+
+/**
+ * json_object_ref:
+ * @object: a #JsonObject
+ *
+ * Increase by one the reference count of a #JsonObject.
+ *
+ * Return value: the passed #JsonObject, with the reference count
+ *   increased by one.
+ */
+JsonObject *
+json_object_ref (JsonObject *object)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (object->ref_count > 0, NULL);
+
+  g_atomic_int_add (&object->ref_count, 1);
+
+  return object;
+}
+
+/**
+ * json_object_unref:
+ * @object: a #JsonObject
+ *
+ * Decreases by one the reference count of a #JsonObject. If the
+ * reference count reaches zero, the object is destroyed and all
+ * its allocated resources are freed.
+ */
+void
+json_object_unref (JsonObject *object)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (object->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&object->ref_count))
+    {
+      g_list_free (object->members_ordered);
+      g_hash_table_destroy (object->members);
+      object->members_ordered = NULL;
+      object->members = NULL;
+
+      g_slice_free (JsonObject, object);
+    }
+}
+
+static inline void
+object_set_member_internal (JsonObject  *object,
+                            const gchar *member_name,
+                            JsonNode    *node)
+{
+  gchar *name = g_strdup (member_name);
+
+  if (g_hash_table_lookup (object->members, name) == NULL)
+    object->members_ordered = g_list_prepend (object->members_ordered, name);
+  else
+    {
+      GList *l;
+
+      /* if the member already exists then we need to replace the
+       * pointer to its name, to avoid keeping invalid pointers
+       * once we replace the key in the hash table
+       */
+      l = g_list_find_custom (object->members_ordered, name, (GCompareFunc) strcmp);
+      if (l != NULL)
+        l->data = name;
+    }
+
+  g_hash_table_replace (object->members, name, node);
+}
+
+/**
+ * json_object_add_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @node: (transfer full): the value of the member
+ *
+ * Adds a member named @member_name and containing @node into a #JsonObject.
+ * The object will take ownership of the #JsonNode.
+ *
+ * This function will return if the @object already contains a member
+ * @member_name.
+ *
+ * Deprecated: 0.8: Use json_object_set_member() instead
+ */
+void
+json_object_add_member (JsonObject  *object,
+                        const gchar *member_name,
+                        JsonNode    *node)
+{
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+  g_return_if_fail (node != NULL);
+
+  if (json_object_has_member (object, member_name))
+    {
+      g_warning ("JsonObject already has a `%s' member of type `%s'",
+                 member_name,
+                 json_node_type_name (node));
+      return;
+    }
+
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @node: (transfer full): the value of the member
+ *
+ * Sets @node as the value of @member_name inside @object.
+ *
+ * If @object already contains a member called @member_name then
+ * the member's current value is overwritten. Otherwise, a new
+ * member is added to @object.
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_member (JsonObject  *object,
+                        const gchar *member_name,
+                        JsonNode    *node)
+{
+  JsonNode *old_node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+  g_return_if_fail (node != NULL);
+
+  old_node = g_hash_table_lookup (object->members, member_name);
+  if (old_node == NULL)
+    goto set_member;
+
+  if (old_node == node)
+    return;
+
+set_member:
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_int_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting an integer @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_int_member (JsonObject  *object,
+                            const gchar *member_name,
+                            gint64       value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_int (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_double_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a floating point @value
+ * of @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_double_member (JsonObject  *object,
+                               const gchar *member_name,
+                               gdouble      value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_double (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_boolean_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a boolean @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_boolean_member (JsonObject  *object,
+                                const gchar *member_name,
+                                gboolean     value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_VALUE);
+  json_node_set_boolean (node, value);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_string_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: the value of the member
+ *
+ * Convenience function for setting a string @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_string_member (JsonObject  *object,
+                               const gchar *member_name,
+                               const gchar *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_VALUE);
+      json_node_set_string (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_null_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function for setting a null @value of
+ * @member_name inside @object.
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_null_member (JsonObject  *object,
+                             const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  node = json_node_new (JSON_NODE_NULL);
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_array_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: (transfer full): the value of the member
+ *
+ * Convenience function for setting an array @value of
+ * @member_name inside @object.
+ *
+ * The @object will take ownership of the passed #JsonArray
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_array_member (JsonObject  *object,
+                              const gchar *member_name,
+                              JsonArray   *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_ARRAY);
+      json_node_take_array (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_set_object_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ * @value: (transfer full): the value of the member
+ *
+ * Convenience function for setting an object @value of
+ * @member_name inside @object.
+ *
+ * The @object will take ownership of the passed #JsonObject
+ *
+ * See also: json_object_set_member()
+ *
+ * Since: 0.8
+ */
+void
+json_object_set_object_member (JsonObject  *object,
+                               const gchar *member_name,
+                               JsonObject  *value)
+{
+  JsonNode *node;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  if (value != NULL)
+    {
+      node = json_node_new (JSON_NODE_OBJECT);
+      json_node_take_object (node, value);
+    }
+  else
+    node = json_node_new (JSON_NODE_NULL);
+
+  object_set_member_internal (object, member_name, node);
+}
+
+/**
+ * json_object_get_members:
+ * @object: a #JsonObject
+ *
+ * Retrieves all the names of the members of a #JsonObject. You can
+ * obtain the value for each member using json_object_get_member().
+ *
+ * Return value: (element-type utf8) (transfer container): a #GList
+ *   of member names. The content of the list is owned by the #JsonObject
+ *   and should never be modified or freed. When you have finished using
+ *   the returned list, use g_list_free() to free the resources it has
+ *   allocated.
+ */
+GList *
+json_object_get_members (JsonObject *object)
+{
+  GList *copy;
+
+  g_return_val_if_fail (object != NULL, NULL);
+
+  copy = g_list_copy (object->members_ordered);
+
+  return g_list_reverse (copy);
+}
+
+/**
+ * json_object_get_values:
+ * @object: a #JsonObject
+ *
+ * Retrieves all the values of the members of a #JsonObject.
+ *
+ * Return value: (element-type JsonNode) (transfer container): a #GList of
+ *   #JsonNode<!-- -->s. The content of the list is owned by the #JsonObject
+ *   and should never be modified or freed. When you have finished using the
+ *   returned list, use g_list_free() to free the resources it has allocated.
+ */
+GList *
+json_object_get_values (JsonObject *object)
+{
+  GList *values, *l;
+
+  g_return_val_if_fail (object != NULL, NULL);
+
+  values = NULL;
+  for (l = object->members_ordered; l != NULL; l = l->next)
+    values = g_list_prepend (values, g_hash_table_lookup (object->members, l->data));
+
+  return values;
+}
+
+/**
+ * json_object_dup_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the JSON object member to access
+ *
+ * Retrieves a copy of the #JsonNode containing the value of @member_name
+ * inside a #JsonObject
+ *
+ * Return value: (transfer full): a copy of the node for the requested
+ *   object member or %NULL. Use json_node_free() when done.
+ *
+ * Since: 0.6
+ */
+JsonNode *
+json_object_dup_member (JsonObject  *object,
+                        const gchar *member_name)
+{
+  JsonNode *retval;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  retval = json_object_get_member (object, member_name);
+  if (!retval)
+    return NULL;
+
+  return json_node_copy (retval);
+}
+
+static inline JsonNode *
+object_get_member_internal (JsonObject  *object,
+                            const gchar *member_name)
+{
+  return g_hash_table_lookup (object->members, member_name);
+}
+
+/**
+ * json_object_get_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the JSON object member to access
+ *
+ * Retrieves the #JsonNode containing the value of @member_name inside
+ * a #JsonObject.
+ *
+ * Return value: (transfer none): a pointer to the node for the requested object
+ *   member, or %NULL
+ */
+JsonNode *
+json_object_get_member (JsonObject  *object,
+                        const gchar *member_name)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  return object_get_member_internal (object, member_name);
+}
+
+/**
+ * json_object_get_int_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the integer value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the integer value of the object's member
+ *
+ * Since: 0.8
+ */
+gint64
+json_object_get_int_member (JsonObject  *object,
+                            const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, 0);
+  g_return_val_if_fail (member_name != NULL, 0);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, 0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
+
+  return json_node_get_int (node);
+}
+
+/**
+ * json_object_get_double_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the floating point value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the floating point value of the object's member
+ *
+ * Since: 0.8
+ */
+gdouble
+json_object_get_double_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, 0.0);
+  g_return_val_if_fail (member_name != NULL, 0.0);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, 0.0);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+
+  return json_node_get_double (node);
+}
+
+/**
+ * json_object_get_boolean_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the boolean value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the boolean value of the object's member
+ *
+ * Since: 0.8
+ */
+gboolean
+json_object_get_boolean_member (JsonObject  *object,
+                                const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, FALSE);
+  g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+
+  return json_node_get_boolean (node);
+}
+
+/**
+ * json_object_get_null_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that checks whether the value
+ * stored in @member_name of @object is null
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: %TRUE if the value is null
+ *
+ * Since: 0.8
+ */
+gboolean
+json_object_get_null_member (JsonObject  *object,
+                             const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  return JSON_NODE_TYPE (node) == JSON_NODE_NULL;
+}
+
+/**
+ * json_object_get_string_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the string value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the string value of the object's member
+ *
+ * Since: 0.8
+ */
+const gchar *
+json_object_get_string_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_string (node);
+}
+
+/**
+ * json_object_get_array_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the array
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: (transfer none): the array inside the object's member
+ *
+ * Since: 0.8
+ */
+JsonArray *
+json_object_get_array_member (JsonObject  *object,
+                              const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_array (node);
+}
+
+/**
+ * json_object_get_object_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the object
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: (transfer none): the object inside the object's member
+ *
+ * Since: 0.8
+ */
+JsonObject *
+json_object_get_object_member (JsonObject  *object,
+                               const gchar *member_name)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (object != NULL, NULL);
+  g_return_val_if_fail (member_name != NULL, NULL);
+
+  node = object_get_member_internal (object, member_name);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
+
+  if (JSON_NODE_HOLDS_NULL (node))
+    return NULL;
+
+  return json_node_get_object (node);
+}
+
+/**
+ * json_object_has_member:
+ * @object: a #JsonObject
+ * @member_name: the name of a JSON object member
+ *
+ * Checks whether @object has a member named @member_name.
+ *
+ * Return value: %TRUE if the JSON object has the requested member
+ */
+gboolean
+json_object_has_member (JsonObject *object,
+                        const gchar *member_name)
+{
+  g_return_val_if_fail (object != NULL, FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+
+  return (g_hash_table_lookup (object->members, member_name) != NULL);
+}
+
+/**
+ * json_object_get_size:
+ * @object: a #JsonObject
+ *
+ * Retrieves the number of members of a #JsonObject.
+ *
+ * Return value: the number of members
+ */
+guint
+json_object_get_size (JsonObject *object)
+{
+  g_return_val_if_fail (object != NULL, 0);
+
+  return g_hash_table_size (object->members);
+}
+
+/**
+ * json_object_remove_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member to remove
+ *
+ * Removes @member_name from @object, freeing its allocated resources.
+ */
+void
+json_object_remove_member (JsonObject  *object,
+                           const gchar *member_name)
+{
+  GList *l;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (member_name != NULL);
+
+  for (l = object->members_ordered; l != NULL; l = l->next)
+    {
+      const gchar *name = l->data;
+
+      if (g_strcmp0 (name, member_name) == 0)
+        {
+          object->members_ordered = g_list_delete_link (object->members_ordered, l);
+          break;
+        }
+    }
+
+  g_hash_table_remove (object->members, member_name);
+}
+
+/**
+ * json_object_foreach_member:
+ * @object: a #JsonObject
+ * @func: (scope call): the function to be called on each member
+ * @data: (closure): data to be passed to the function
+ *
+ * Iterates over all members of @object and calls @func on
+ * each one of them.
+ *
+ * It is safe to change the value of a #JsonNode of the @object
+ * from within the iterator @func, but it is not safe to add or
+ * remove members from the @object.
+ *
+ * Since: 0.8
+ */
+void
+json_object_foreach_member (JsonObject        *object,
+                            JsonObjectForeach  func,
+                            gpointer           data)
+{
+  GList *members, *l;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (func != NULL);
+
+  /* the list is stored in reverse order to have constant time additions */
+  members = g_list_last (object->members_ordered);
+  for (l = members; l != NULL; l = l->prev)
+    {
+      const gchar *member_name = l->data;
+      JsonNode *member_node = g_hash_table_lookup (object->members, member_name);
+
+      func (object, member_name, member_node, data);
+    }
+}
diff --git a/src/glib-jsonrpc/json-glib/json-parser.c b/src/glib-jsonrpc/json-glib/json-parser.c
new file mode 100644
index 0000000..4fe6bef
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-parser.c
@@ -0,0 +1,1434 @@
+/* json-parser.c - JSON streams parser
+ * 
+ * This file is part of JSON-GLib
+ *
+ * Copyright  2007, 2008, 2009 OpenedHand Ltd
+ * Copyright  2009, 2010 Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:json-parser
+ * @short_description: Parse JSON data streams
+ *
+ * #JsonParser provides an object for parsing a JSON data stream, either
+ * inside a file or inside a static buffer.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#if 0
+#include <glib/gi18n-lib.h>
+#else
+#define _(s) s
+#endif
+
+#include "json-types-private.h"
+
+#include "json-debug.h"
+#include "json-marshal.h"
+#include "json-parser.h"
+#include "json-scanner.h"
+
+GQuark
+json_parser_error_quark (void)
+{
+  return g_quark_from_static_string ("json-parser-error");
+}
+
+#define JSON_PARSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_PARSER, JsonParserPrivate))
+
+struct _JsonParserPrivate
+{
+  JsonNode *root;
+  JsonNode *current_node;
+
+  JsonScanner *scanner;
+
+  JsonParserError error_code;
+  GError *last_error;
+
+  gchar *variable_name;
+  gchar *filename;
+
+  guint has_assignment : 1;
+  guint is_filename    : 1;
+};
+
+static const gchar symbol_names[] =
+  "true\0"
+  "false\0"
+  "null\0"
+  "var\0";
+
+static const struct
+{
+  guint name_offset;
+  guint token;
+} symbols[] = {
+  {  0, JSON_TOKEN_TRUE  },
+  {  5, JSON_TOKEN_FALSE },
+  { 11, JSON_TOKEN_NULL  },
+  { 16, JSON_TOKEN_VAR   }
+};
+
+static const guint n_symbols = G_N_ELEMENTS (symbols);
+
+enum
+{
+  PARSE_START,
+  OBJECT_START,
+  OBJECT_MEMBER,
+  OBJECT_END,
+  ARRAY_START,
+  ARRAY_ELEMENT,
+  ARRAY_END,
+  PARSE_END,
+  ERROR,
+
+  LAST_SIGNAL
+};
+
+static guint parser_signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (JsonParser, json_parser, G_TYPE_OBJECT);
+
+static guint json_parse_array  (JsonParser   *parser,
+                                JsonScanner  *scanner,
+                                JsonNode    **node);
+static guint json_parse_object (JsonParser   *parser,
+                                JsonScanner  *scanner,
+                                JsonNode    **node);
+
+static inline void
+json_parser_clear (JsonParser *parser)
+{
+  JsonParserPrivate *priv = parser->priv;
+
+  g_free (priv->variable_name);
+  priv->variable_name = NULL;
+
+  if (priv->last_error)
+    {
+      g_error_free (priv->last_error);
+      priv->last_error = NULL;
+    }
+
+  if (priv->root)
+    {
+      json_node_free (priv->root);
+      priv->root = NULL;
+    }
+}
+
+static void
+json_parser_dispose (GObject *gobject)
+{
+  json_parser_clear (JSON_PARSER (gobject));
+
+  G_OBJECT_CLASS (json_parser_parent_class)->dispose (gobject);
+}
+
+static void
+json_parser_finalize (GObject *gobject)
+{
+  JsonParserPrivate *priv = JSON_PARSER (gobject)->priv;
+
+  g_free (priv->variable_name);
+  g_free (priv->filename);
+
+  G_OBJECT_CLASS (json_parser_parent_class)->finalize (gobject);
+}
+
+static void
+json_parser_class_init (JsonParserClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (JsonParserPrivate));
+
+  gobject_class->dispose = json_parser_dispose;
+  gobject_class->finalize = json_parser_finalize;
+
+  /**
+   * JsonParser::parse-start:
+   * @parser: the #JsonParser that received the signal
+   * 
+   * The ::parse-start signal is emitted when the parser began parsing
+   * a JSON data stream.
+   */
+  parser_signals[PARSE_START] =
+    g_signal_new ("parse-start",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, parse_start),
+                  NULL, NULL,
+                  _json_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * JsonParser::parse-end:
+   * @parser: the #JsonParser that received the signal
+   *
+   * The ::parse-end signal is emitted when the parser successfully
+   * finished parsing a JSON data stream
+   */
+  parser_signals[PARSE_END] =
+    g_signal_new ("parse-end",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, parse_end),
+                  NULL, NULL,
+                  _json_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * JsonParser::object-start:
+   * @parser: the #JsonParser that received the signal
+   * 
+   * The ::object-start signal is emitted each time the #JsonParser
+   * starts parsing a #JsonObject.
+   */
+  parser_signals[OBJECT_START] =
+    g_signal_new ("object-start",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, object_start),
+                  NULL, NULL,
+                  _json_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * JsonParser::object-member:
+   * @parser: the #JsonParser that received the signal
+   * @object: a #JsonObject
+   * @member_name: the name of the newly parsed member
+   *
+   * The ::object-member signal is emitted each time the #JsonParser
+   * has successfully parsed a single member of a #JsonObject. The
+   * object and member are passed to the signal handlers.
+   */
+  parser_signals[OBJECT_MEMBER] =
+    g_signal_new ("object-member",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, object_member),
+                  NULL, NULL,
+                  _json_marshal_VOID__BOXED_STRING,
+                  G_TYPE_NONE, 2,
+                  JSON_TYPE_OBJECT,
+                  G_TYPE_STRING);
+  /**
+   * JsonParser::object-end:
+   * @parser: the #JsonParser that received the signal
+   * @object: the parsed #JsonObject
+   *
+   * The ::object-end signal is emitted each time the #JsonParser
+   * has successfully parsed an entire #JsonObject.
+   */
+  parser_signals[OBJECT_END] =
+    g_signal_new ("object-end",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, object_end),
+                  NULL, NULL,
+                  _json_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  JSON_TYPE_OBJECT);
+  /**
+   * JsonParser::array-start:
+   * @parser: the #JsonParser that received the signal
+   *
+   * The ::array-start signal is emitted each time the #JsonParser
+   * starts parsing a #JsonArray
+   */
+  parser_signals[ARRAY_START] =
+    g_signal_new ("array-start",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, array_start),
+                  NULL, NULL,
+                  _json_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+  /**
+   * JsonParser::array-element:
+   * @parser: the #JsonParser that received the signal
+   * @array: a #JsonArray
+   * @index_: the index of the newly parsed element
+   *
+   * The ::array-element signal is emitted each time the #JsonParser
+   * has successfully parsed a single element of a #JsonArray. The
+   * array and element index are passed to the signal handlers.
+   */
+  parser_signals[ARRAY_ELEMENT] =
+    g_signal_new ("array-element",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, array_element),
+                  NULL, NULL,
+                  _json_marshal_VOID__BOXED_INT,
+                  G_TYPE_NONE, 2,
+                  JSON_TYPE_ARRAY,
+                  G_TYPE_INT);
+  /**
+   * JsonParser::array-end:
+   * @parser: the #JsonParser that received the signal
+   * @array: the parsed #JsonArray
+   *
+   * The ::array-end signal is emitted each time the #JsonParser
+   * has successfully parsed an entire #JsonArray
+   */
+  parser_signals[ARRAY_END] =
+    g_signal_new ("array-end",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, array_end),
+                  NULL, NULL,
+                  _json_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  JSON_TYPE_ARRAY);
+  /**
+   * JsonParser::error:
+   * @parser: the parser instance that received the signal
+   * @error: a pointer to the #GError
+   *
+   * The ::error signal is emitted each time a #JsonParser encounters
+   * an error in a JSON stream.
+   */
+  parser_signals[ERROR] =
+    g_signal_new ("error",
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (JsonParserClass, error),
+                  NULL, NULL,
+                  _json_marshal_VOID__POINTER,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_POINTER);
+}
+
+static void
+json_parser_init (JsonParser *parser)
+{
+  JsonParserPrivate *priv;
+
+  parser->priv = priv = JSON_PARSER_GET_PRIVATE (parser);
+
+  priv->root = NULL;
+  priv->current_node = NULL;
+
+  priv->error_code = JSON_PARSER_ERROR_PARSE;
+  priv->last_error = NULL;
+
+  priv->has_assignment = FALSE;
+  priv->variable_name = NULL;
+
+  priv->is_filename = FALSE;
+  priv->filename = FALSE;
+}
+
+static guint
+json_parse_value (JsonParser   *parser,
+                  JsonScanner  *scanner,
+                  guint         token,
+                  JsonNode    **node)
+{
+  JsonParserPrivate *priv = parser->priv;
+  JsonNode *current_node = priv->current_node;
+  gboolean is_negative = FALSE;
+
+  if (token == '-')
+    {
+      guint next_token = json_scanner_peek_next_token (scanner);
+
+      if (next_token == G_TOKEN_INT ||
+          next_token == G_TOKEN_FLOAT)
+        {
+           is_negative = TRUE;
+           token = json_scanner_get_next_token (scanner);
+        }
+      else
+        return G_TOKEN_INT;
+    }
+
+  switch (token)
+    {
+    case G_TOKEN_INT:
+      *node = json_node_new (JSON_NODE_VALUE);
+      JSON_NOTE (PARSER, "abs(node): %" G_GINT64_FORMAT " (sign: %s)",
+                 scanner->value.v_int64,
+                 is_negative ? "negative" : "positive");
+      json_node_set_int (*node, is_negative ? scanner->value.v_int64 * -1
+                                            : scanner->value.v_int64);
+      break;
+
+    case G_TOKEN_FLOAT:
+      *node = json_node_new (JSON_NODE_VALUE);
+      JSON_NOTE (PARSER, "abs(node): %.6f (sign: %s)",
+                 scanner->value.v_float,
+                 is_negative ? "negative" : "positive");
+      json_node_set_double (*node, is_negative ? scanner->value.v_float * -1.0
+                                               : scanner->value.v_float);
+      break;
+
+    case G_TOKEN_STRING:
+      *node = json_node_new (JSON_NODE_VALUE);
+      JSON_NOTE (PARSER, "node: '%s'",
+                 scanner->value.v_string);
+      json_node_set_string (*node, scanner->value.v_string);
+      break;
+
+    case JSON_TOKEN_TRUE:
+    case JSON_TOKEN_FALSE:
+      *node = json_node_new (JSON_NODE_VALUE);
+      JSON_NOTE (PARSER, "node: '%s'",
+                 JSON_TOKEN_TRUE ? "<true>" : "<false>");
+      json_node_set_boolean (*node, token == JSON_TOKEN_TRUE ? TRUE : FALSE);
+      break;
+
+    case JSON_TOKEN_NULL:
+      *node = json_node_new (JSON_NODE_NULL);
+      JSON_NOTE (PARSER, "node: <null>");
+      break;
+
+    default:
+      {
+        JsonNodeType cur_type;
+
+        *node = NULL;
+
+        cur_type = json_node_get_node_type (current_node);
+        if (cur_type == JSON_NODE_ARRAY)
+          return G_TOKEN_RIGHT_BRACE;
+        else if (cur_type == JSON_NODE_OBJECT)
+          return G_TOKEN_RIGHT_CURLY;
+        else
+          {
+            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+            return G_TOKEN_SYMBOL;
+          }
+      }
+    }
+
+  return G_TOKEN_NONE;
+}
+
+static guint
+json_parse_array (JsonParser   *parser,
+                  JsonScanner  *scanner,
+                  JsonNode    **node)
+{
+  JsonParserPrivate *priv = parser->priv;
+  JsonNode *old_current;
+  JsonArray *array;
+  guint token;
+  gint idx;
+
+  old_current = priv->current_node;
+  priv->current_node = json_node_new (JSON_NODE_ARRAY);
+
+  array = json_array_new ();
+
+  token = json_scanner_get_next_token (scanner);
+  g_assert (token == G_TOKEN_LEFT_BRACE);
+
+  g_signal_emit (parser, parser_signals[ARRAY_START], 0);
+
+  idx = 0;
+  while (token != G_TOKEN_RIGHT_BRACE)
+    {
+      guint next_token = json_scanner_peek_next_token (scanner);
+      JsonNode *element = NULL;
+
+      /* parse the element */
+      switch (next_token)
+        {
+        case G_TOKEN_LEFT_BRACE:
+          JSON_NOTE (PARSER, "Nested array at index %d", idx);
+          token = json_parse_array (parser, scanner, &element);
+          break;
+
+        case G_TOKEN_LEFT_CURLY:
+          JSON_NOTE (PARSER, "Nested object at index %d", idx);
+          token = json_parse_object (parser, scanner, &element);
+          break;
+
+        case G_TOKEN_INT:
+        case G_TOKEN_FLOAT:
+        case G_TOKEN_STRING:
+        case '-':
+        case JSON_TOKEN_TRUE:
+        case JSON_TOKEN_FALSE:
+        case JSON_TOKEN_NULL:
+          token = json_scanner_get_next_token (scanner);
+          token = json_parse_value (parser, scanner, token, &element);
+          break;
+
+        case G_TOKEN_RIGHT_BRACE:
+          goto array_done;
+
+        default:
+          if (next_token != G_TOKEN_RIGHT_BRACE)
+            token = G_TOKEN_RIGHT_BRACE;
+          break;
+        }
+
+      if (token != G_TOKEN_NONE || element == NULL)
+        {
+          /* the json_parse_* functions will have set the error code */
+          json_array_unref (array);
+          json_node_free (priv->current_node);
+          priv->current_node = old_current;
+
+          return token;
+        }
+
+      next_token = json_scanner_peek_next_token (scanner);
+
+      if (next_token == G_TOKEN_COMMA)
+        {
+          token = json_scanner_get_next_token (scanner);
+          next_token = json_scanner_peek_next_token (scanner);
+
+          /* look for trailing commas */
+          if (next_token == G_TOKEN_RIGHT_BRACE)
+            {
+              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+
+              json_array_unref (array);
+              json_node_free (priv->current_node);
+              json_node_free (element);
+              priv->current_node = old_current;
+
+              return G_TOKEN_RIGHT_BRACE;
+            }
+        }
+
+      JSON_NOTE (PARSER, "Array element %d completed", idx + 1);
+      json_node_set_parent (element, priv->current_node);
+      json_array_add_element (array, element);
+
+      g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0,
+                     array,
+                     idx);
+
+      token = next_token;
+    }
+
+array_done:
+  json_scanner_get_next_token (scanner);
+
+  json_node_take_array (priv->current_node, array);
+  json_node_set_parent (priv->current_node, old_current);
+
+  g_signal_emit (parser, parser_signals[ARRAY_END], 0, array);
+
+  if (node != NULL && *node == NULL)
+    *node = priv->current_node;
+
+  priv->current_node = old_current;
+
+  return G_TOKEN_NONE;
+}
+
+static guint
+json_parse_object (JsonParser   *parser,
+                   JsonScanner  *scanner,
+                   JsonNode    **node)
+{
+  JsonParserPrivate *priv = parser->priv;
+  JsonObject *object;
+  JsonNode *old_current;
+  guint token;
+
+  old_current = priv->current_node;
+  priv->current_node = json_node_new (JSON_NODE_OBJECT);
+
+  object = json_object_new ();
+
+  token = json_scanner_get_next_token (scanner);
+  g_assert (token == G_TOKEN_LEFT_CURLY);
+
+  g_signal_emit (parser, parser_signals[OBJECT_START], 0);
+
+  while (token != G_TOKEN_RIGHT_CURLY)
+    {
+      guint next_token = json_scanner_peek_next_token (scanner);
+      JsonNode *member = NULL;
+      gchar *name;
+
+      /* we need to abort here because empty objects do not
+       * have member names
+       */
+      if (next_token == G_TOKEN_RIGHT_CURLY)
+        break;
+
+      /* parse the member's name */
+      if (next_token != G_TOKEN_STRING)
+        {
+          JSON_NOTE (PARSER, "Missing object member name");
+
+          priv->error_code = JSON_PARSER_ERROR_PARSE;
+
+          json_object_unref (object);
+          json_node_free (priv->current_node);
+          priv->current_node = old_current;
+
+          return G_TOKEN_STRING;
+        }
+
+      /* member name */
+      token = json_scanner_get_next_token (scanner);
+      name = g_strdup (scanner->value.v_string);
+      JSON_NOTE (PARSER, "Object member '%s'", name);
+
+      /* a colon separates names from values */
+      next_token = json_scanner_peek_next_token (scanner);
+      if (next_token != ':')
+        {
+          JSON_NOTE (PARSER, "Missing object member name separator");
+
+          priv->error_code = JSON_PARSER_ERROR_MISSING_COLON;
+
+          g_free (name);
+          json_object_unref (object);
+          json_node_free (priv->current_node);
+          priv->current_node = old_current;
+
+          return ':';
+        }
+
+      /* we swallow the ':' */
+      token = json_scanner_get_next_token (scanner);
+      g_assert (token == ':');
+      next_token = json_scanner_peek_next_token (scanner);
+
+      /* parse the member's value */
+      switch (next_token)
+        {
+        case G_TOKEN_LEFT_BRACE:
+          JSON_NOTE (PARSER, "Nested array at member %s", name);
+          token = json_parse_array (parser, scanner, &member);
+          break;
+
+        case G_TOKEN_LEFT_CURLY:
+          JSON_NOTE (PARSER, "Nested object at member %s", name);
+          token = json_parse_object (parser, scanner, &member);
+          break;
+
+        case G_TOKEN_INT:
+        case G_TOKEN_FLOAT:
+        case G_TOKEN_STRING:
+        case '-':
+        case JSON_TOKEN_TRUE:
+        case JSON_TOKEN_FALSE:
+        case JSON_TOKEN_NULL:
+          token = json_scanner_get_next_token (scanner);
+          token = json_parse_value (parser, scanner, token, &member);
+          break;
+
+        default:
+          /* once a member name is defined we need a value */
+          token = G_TOKEN_SYMBOL;
+          break;
+        }
+
+      if (token != G_TOKEN_NONE || member == NULL)
+        {
+          /* the json_parse_* functions will have set the error code */
+          g_free (name);
+          json_object_unref (object);
+          json_node_free (priv->current_node);
+          priv->current_node = old_current;
+
+          return token;
+        }
+
+      next_token = json_scanner_peek_next_token (scanner);
+      if (next_token == G_TOKEN_COMMA)
+        {
+          token = json_scanner_get_next_token (scanner);
+          next_token = json_scanner_peek_next_token (scanner);
+
+          /* look for trailing commas */
+          if (next_token == G_TOKEN_RIGHT_CURLY)
+            {
+              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+
+              json_object_unref (object);
+              json_node_free (member);
+              json_node_free (priv->current_node);
+              priv->current_node = old_current;
+
+              return G_TOKEN_RIGHT_BRACE;
+            }
+        }
+      else if (next_token == G_TOKEN_STRING)
+        {
+          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
+
+          json_object_unref (object);
+          json_node_free (member);
+          json_node_free (priv->current_node);
+          priv->current_node = old_current;
+
+          return G_TOKEN_COMMA;
+        }
+
+      JSON_NOTE (PARSER, "Object member '%s' completed", name);
+      json_node_set_parent (member, priv->current_node);
+      json_object_set_member (object, name, member);
+
+      g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0,
+                     object,
+                     name);
+
+      g_free (name);
+
+      token = next_token;
+    }
+
+  json_scanner_get_next_token (scanner);
+
+  json_node_take_object (priv->current_node, object);
+  json_node_set_parent (priv->current_node, old_current);
+
+  g_signal_emit (parser, parser_signals[OBJECT_END], 0, object);
+
+  if (node != NULL && *node == NULL)
+    *node = priv->current_node;
+
+  priv->current_node = old_current;
+
+  return G_TOKEN_NONE;
+}
+
+static guint
+json_parse_statement (JsonParser  *parser,
+                      JsonScanner *scanner)
+{
+  JsonParserPrivate *priv = parser->priv;
+  guint token;
+
+  token = json_scanner_peek_next_token (scanner);
+  switch (token)
+    {
+    case G_TOKEN_LEFT_CURLY:
+      JSON_NOTE (PARSER, "Statement is object declaration");
+      return json_parse_object (parser, scanner, &priv->root);
+
+    case G_TOKEN_LEFT_BRACE:
+      JSON_NOTE (PARSER, "Statement is array declaration");
+      return json_parse_array (parser, scanner, &priv->root);
+
+    /* some web APIs are not only passing the data structures: they are
+     * also passing an assigment, which makes parsing horribly complicated
+     * only because web developers are lazy, and writing "var foo = " is
+     * evidently too much to request from them.
+     */
+    case JSON_TOKEN_VAR:
+      {
+        guint next_token;
+        gchar *name;
+
+        JSON_NOTE (PARSER, "Statement is an assignment");
+
+        /* swallow the 'var' token... */
+        token = json_scanner_get_next_token (scanner);
+
+        /* ... swallow the variable name... */
+        next_token = json_scanner_get_next_token (scanner);
+        if (next_token != G_TOKEN_IDENTIFIER)
+          {
+            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+            return G_TOKEN_IDENTIFIER;
+          }
+
+        name = g_strdup (scanner->value.v_identifier);
+
+        /* ... and finally swallow the '=' */
+        next_token = json_scanner_get_next_token (scanner);
+        if (next_token != '=')
+          return '=';
+
+        priv->has_assignment = TRUE;
+        priv->variable_name = name;
+
+        token = json_parse_statement (parser, scanner);
+
+        /* remove the trailing semi-colon */
+        next_token = json_scanner_peek_next_token (scanner);
+        if (next_token == ';')
+          {
+            token = json_scanner_get_next_token (scanner);
+            return G_TOKEN_NONE;
+          }
+
+        return token;
+      }
+      break;
+
+    case JSON_TOKEN_NULL:
+    case JSON_TOKEN_TRUE:
+    case JSON_TOKEN_FALSE:
+    case '-':
+    case G_TOKEN_INT:
+    case G_TOKEN_FLOAT:
+    case G_TOKEN_STRING:
+      JSON_NOTE (PARSER, "Statement is a value");
+      token = json_scanner_get_next_token (scanner);
+      return json_parse_value (parser, scanner, token, &priv->root);
+
+    default:
+      JSON_NOTE (PARSER, "Unknown statement");
+      json_scanner_get_next_token (scanner);
+      priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+      return G_TOKEN_SYMBOL;
+    }
+}
+
+static void
+json_scanner_msg_handler (JsonScanner *scanner,
+                          gchar       *message,
+                          gboolean     is_error)
+{
+  JsonParser *parser = scanner->user_data;
+  JsonParserPrivate *priv = parser->priv;
+
+  if (is_error)
+    {
+      GError *error = NULL;
+
+      /* translators: %s: is the file name, %d is the line number
+       * and %s is the error message
+       */
+      g_set_error (&error, JSON_PARSER_ERROR,
+                   priv->error_code,
+                   _("%s:%d: Parse error: %s"),
+                   priv->is_filename ? priv->filename : "<none>",
+                   scanner->line,
+                   message);
+      
+      parser->priv->last_error = error;
+      g_signal_emit (parser, parser_signals[ERROR], 0, error);
+    }
+  else
+    g_warning ("%s:%d: Parse error: %s",
+               priv->is_filename ? priv->filename : "<none>",
+               scanner->line,
+               message);
+}
+
+static JsonScanner *
+json_scanner_create (JsonParser *parser)
+{
+  JsonScanner *scanner;
+  gint i;
+
+  scanner = json_scanner_new ();
+  scanner->msg_handler = json_scanner_msg_handler;
+  scanner->user_data = parser;
+
+  for (i = 0; i < n_symbols; i++)
+    {
+      json_scanner_scope_add_symbol (scanner, 0,
+                                     symbol_names + symbols[i].name_offset,
+                                     GINT_TO_POINTER (symbols[i].token));
+    }
+
+  return scanner;
+}
+
+/**
+ * json_parser_new:
+ * 
+ * Creates a new #JsonParser instance. You can use the #JsonParser to
+ * load a JSON stream from either a file or a buffer and then walk the
+ * hierarchy using the data types API.
+ *
+ * Return value: the newly created #JsonParser. Use g_object_unref()
+ *   to release all the memory it allocates.
+ */
+JsonParser *
+json_parser_new (void)
+{
+  return g_object_new (JSON_TYPE_PARSER, NULL);
+}
+
+static gboolean
+json_parser_load (JsonParser   *parser,
+                  const gchar  *data,
+                  gsize         length,
+                  GError      **error)
+{
+  JsonParserPrivate *priv = parser->priv;
+  JsonScanner *scanner;
+  gboolean done;
+  gboolean retval = TRUE;
+  gint i;
+
+  json_parser_clear (parser);
+
+  scanner = json_scanner_create (parser);
+  json_scanner_input_text (scanner, data, length);
+
+  priv->scanner = scanner;
+
+  g_signal_emit (parser, parser_signals[PARSE_START], 0);
+
+  done = FALSE;
+  while (!done)
+    {
+      if (json_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
+        done = TRUE;
+      else
+        {
+          guint expected_token;
+          gint cur_token;
+
+          /* we try to show the expected token, if possible */
+          expected_token = json_parse_statement (parser, scanner);
+          if (expected_token != G_TOKEN_NONE)
+            {
+              const gchar *symbol_name;
+              gchar *msg;
+
+              cur_token = scanner->token;
+              msg = NULL;
+              symbol_name = NULL;
+
+              if (scanner->scope_id == 0)
+                {
+                  if (expected_token > JSON_TOKEN_INVALID &&
+                      expected_token < JSON_TOKEN_LAST)
+                    {
+                      for (i = 0; i < n_symbols; i++)
+                        if (symbols[i].token == expected_token)
+                          symbol_name = symbol_names + symbols[i].name_offset;
+
+                      if (!msg)
+                        msg = g_strconcat ("e.g. '", symbol_name, "'", NULL);
+                    }
+
+                  if (cur_token > JSON_TOKEN_INVALID &&
+                      cur_token < JSON_TOKEN_LAST)
+                    {
+                      symbol_name = "???";
+
+                      for (i = 0; i < n_symbols; i++)
+                        if (symbols[i].token == cur_token)
+                          symbol_name = symbol_names + symbols[i].name_offset;
+                    }
+                }
+
+              /* this will emit the ::error signal via the custom
+               * message handler we install
+               */
+              json_scanner_unexp_token (scanner, expected_token,
+                                        NULL, "value",
+                                        symbol_name, msg,
+                                        TRUE);
+
+              /* and this will propagate the error we create in the
+               * same message handler
+               */
+              if (priv->last_error)
+                {
+                  g_propagate_error (error, priv->last_error);
+                  priv->last_error = NULL;
+                }
+
+              retval = FALSE;
+
+              g_free (msg);
+              done = TRUE;
+            }
+        }
+    }
+
+  g_signal_emit (parser, parser_signals[PARSE_END], 0);
+
+  /* remove the scanner */
+  json_scanner_destroy (scanner);
+  priv->scanner = NULL;
+  priv->current_node = NULL;
+
+  return retval;
+}
+
+/**
+ * json_parser_load_from_file:
+ * @parser: a #JsonParser
+ * @filename: the path for the file to parse
+ * @error: return location for a #GError, or %NULL
+ *
+ * Loads a JSON stream from the content of @filename and parses it. See
+ * json_parser_load_from_data().
+ *
+ * Return value: %TRUE if the file was successfully loaded and parsed.
+ *   In case of error, @error is set accordingly and %FALSE is returned
+ */
+gboolean
+json_parser_load_from_file (JsonParser   *parser,
+                            const gchar  *filename,
+                            GError      **error)
+{
+  JsonParserPrivate *priv;
+  GError *internal_error;
+  gchar *data;
+  gsize length;
+  gboolean retval = TRUE;
+
+  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+
+  priv = parser->priv;
+
+  internal_error = NULL;
+  if (!g_file_get_contents (filename, &data, &length, &internal_error))
+    {
+      g_propagate_error (error, internal_error);
+      return FALSE;
+    }
+
+  g_free (priv->filename);
+
+  priv->is_filename = TRUE;
+  priv->filename = g_strdup (filename);
+
+  if (!json_parser_load (parser, data, length, &internal_error))
+    {
+      g_propagate_error (error, internal_error);
+      retval = FALSE;
+    }
+
+  g_free (data);
+
+  return retval;
+}
+
+/**
+ * json_parser_load_from_data:
+ * @parser: a #JsonParser
+ * @data: the buffer to parse
+ * @length: the length of the buffer, or -1
+ * @error: return location for a #GError, or %NULL
+ *
+ * Loads a JSON stream from a buffer and parses it. You can call this function
+ * multiple times with the same #JsonParser object, but the contents of the
+ * parser will be destroyed each time.
+ *
+ * Return value: %TRUE if the buffer was succesfully parser. In case
+ *   of error, @error is set accordingly and %FALSE is returned
+ */
+gboolean
+json_parser_load_from_data (JsonParser   *parser,
+                            const gchar  *data,
+                            gssize        length,
+                            GError      **error)
+{
+  JsonParserPrivate *priv;
+  GError *internal_error;
+  gboolean retval = TRUE;
+
+  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  priv = parser->priv;
+
+  if (length < 0)
+    length = strlen (data);
+
+  priv->is_filename = FALSE;
+  g_free (priv->filename);
+  priv->filename = NULL;
+
+  internal_error = NULL;
+  if (!json_parser_load (parser, data, length, &internal_error))
+    {
+      g_propagate_error (error, internal_error);
+      retval = FALSE;
+    }
+
+  return retval;
+}
+
+/**
+ * json_parser_get_root:
+ * @parser: a #JsonParser
+ *
+ * Retrieves the top level node from the parsed JSON stream.
+ *
+ * Return value: (transfer none): the root #JsonNode . The returned
+ *   node is owned by the #JsonParser and should never be modified
+ *   or freed.
+ */
+JsonNode *
+json_parser_get_root (JsonParser *parser)
+{
+  g_return_val_if_fail (JSON_IS_PARSER (parser), NULL);
+
+  return parser->priv->root;
+}
+
+/**
+ * json_parser_get_current_line:
+ * @parser: a #JsonParser
+ *
+ * Retrieves the line currently parsed, starting from 1.
+ *
+ * This function has defined behaviour only while parsing; calling this
+ * function from outside the signal handlers emitted by #JsonParser will
+ * yield 0.
+ *
+ * Return value: the currently parsed line, or 0.
+ */
+guint
+json_parser_get_current_line (JsonParser *parser)
+{
+  g_return_val_if_fail (JSON_IS_PARSER (parser), 0);
+
+  if (parser->priv->scanner)
+    return json_scanner_cur_line (parser->priv->scanner);
+
+  return 0;
+}
+
+/**
+ * json_parser_get_current_pos:
+ * @parser: a #JsonParser
+ *
+ * Retrieves the current position inside the current line, starting
+ * from 0.
+ *
+ * This function has defined behaviour only while parsing; calling this
+ * function from outside the signal handlers emitted by #JsonParser will
+ * yield 0.
+ *
+ * Return value: the position in the current line, or 0.
+ */
+guint
+json_parser_get_current_pos (JsonParser *parser)
+{
+  g_return_val_if_fail (JSON_IS_PARSER (parser), 0);
+
+  if (parser->priv->scanner)
+    return json_scanner_cur_line (parser->priv->scanner);
+
+  return 0;
+}
+
+/**
+ * json_parser_has_assignment:
+ * @parser: a #JsonParser
+ * @variable_name: (out) (allow-none) (transfer none): Return location for the variable
+ *   name, or %NULL
+ *
+ * A JSON data stream might sometimes contain an assignment, like:
+ *
+ * |[
+ *   var _json_data = { "member_name" : [ ...
+ * ]|
+ *
+ * even though it would technically constitute a violation of the RFC.
+ *
+ * #JsonParser will ignore the left hand identifier and parse the right
+ * hand value of the assignment. #JsonParser will record, though, the
+ * existence of the assignment in the data stream and the variable name
+ * used.
+ *
+ * Return value: %TRUE if there was an assignment, %FALSE otherwise. If
+ *   @variable_name is not %NULL it will be set to the name of the variable
+ *   used in the assignment. The string is owned by #JsonParser and should
+ *   never be modified or freed.
+ *
+ * Since: 0.4
+ */
+gboolean
+json_parser_has_assignment (JsonParser  *parser,
+                            gchar      **variable_name)
+{
+  JsonParserPrivate *priv;
+
+  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+
+  priv = parser->priv;
+
+  if (priv->has_assignment && variable_name)
+    *variable_name = priv->variable_name;
+
+  return priv->has_assignment;
+}
+
+#define GET_DATA_BLOCK_SIZE     8192
+
+/**
+ * json_parser_load_from_stream:
+ * @parser: a #JsonParser
+ * @stream: an open #GInputStream
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: the return location for a #GError, or %NULL
+ *
+ * Loads the contents of an input stream and parses them.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the @cancellable object from another thread. If the
+ * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be set
+ * on the passed @error.
+ *
+ * Return value: %TRUE if the data stream was successfully read and
+ *   parsed, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_parser_load_from_stream (JsonParser    *parser,
+                              GInputStream  *stream,
+                              GCancellable  *cancellable,
+                              GError       **error)
+{
+  GByteArray *content;
+  gsize pos;
+  gssize res;
+  gboolean retval = FALSE;
+
+  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+  g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
+  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+
+  content = g_byte_array_new ();
+  pos = 0;
+
+  g_byte_array_set_size (content, pos + GET_DATA_BLOCK_SIZE + 1);
+  while ((res = g_input_stream_read (stream, content->data + pos,
+                                     GET_DATA_BLOCK_SIZE,
+                                     cancellable, error)) > 0)
+    {
+      pos += res;
+      g_byte_array_set_size (content, pos + GET_DATA_BLOCK_SIZE + 1);
+    }
+
+  if (res < 0)
+    {
+      /* error has already been set */
+      retval = FALSE;
+      goto out;
+    }
+
+  /* zero-terminate the content; we allocated an extra byte for this */
+  content->data[pos] = 0;
+
+  retval = json_parser_load (parser, (const gchar *) content->data, content->len, error);
+
+out:
+  g_byte_array_free (content, TRUE);
+
+  return retval;
+}
+
+typedef struct _LoadStreamData
+{
+  JsonParser *parser;
+  GError *error;
+  GCancellable *cancellable;
+  GAsyncReadyCallback callback;
+  gpointer user_data;
+  GByteArray *content;
+  gsize pos;
+} LoadStreamData;
+
+static void
+load_stream_data_free (gpointer data)
+{
+  LoadStreamData *closure;
+
+  if (G_UNLIKELY (data == NULL))
+    return;
+
+  closure = data;
+
+  if (closure->error)
+    g_error_free (closure->error);
+
+  if (closure->cancellable)
+    g_object_unref (closure->cancellable);
+
+  if (closure->content)
+    g_byte_array_free (closure->content, TRUE);
+
+  g_object_unref (closure->parser);
+
+  g_free (closure);
+}
+
+static void
+load_stream_data_read_callback (GObject      *object,
+                                GAsyncResult *read_res,
+                                gpointer      user_data)
+{
+  GInputStream *stream = G_INPUT_STREAM (object);
+  LoadStreamData *data = user_data;
+  GError *error = NULL;
+  gssize read_size;
+
+  read_size = g_input_stream_read_finish (stream, read_res, &error);
+  if (read_size < 0)
+    {
+      if (error != NULL)
+        data->error = error;
+      else
+        {
+          GSimpleAsyncResult *res;
+
+          /* EOF */
+          res = g_simple_async_result_new (G_OBJECT (data->parser),
+                                           data->callback,
+                                           data->user_data,
+                                           json_parser_load_from_stream_async);
+          g_simple_async_result_set_op_res_gpointer (res, data, load_stream_data_free);
+          g_simple_async_result_complete (res);
+          g_object_unref (res);
+        }
+    }
+  else if (read_size > 0)
+    {
+      data->pos += read_size;
+
+      g_byte_array_set_size (data->content, data->pos + GET_DATA_BLOCK_SIZE);
+
+      g_input_stream_read_async (stream, data->content->data + data->pos,
+                                 GET_DATA_BLOCK_SIZE,
+                                 0,
+                                 data->cancellable,
+                                 load_stream_data_read_callback,
+                                 data);
+    }
+  else
+    {
+      GSimpleAsyncResult *res;
+
+      res = g_simple_async_result_new (G_OBJECT (data->parser),
+                                       data->callback,
+                                       data->user_data,
+                                       json_parser_load_from_stream_async);
+      g_simple_async_result_set_op_res_gpointer (res, data, load_stream_data_free);
+      g_simple_async_result_complete (res);
+      g_object_unref (res);
+    }
+}
+
+/**
+ * json_parser_load_from_stream_finish:
+ * @parser: a #JsonParser
+ * @result: a #GAsyncResult
+ * @error: the return location for a #GError or %NULL
+ *
+ * Finishes an asynchronous stream loading started with
+ * json_parser_load_from_stream_async().
+ *
+ * Return value: %TRUE if the content of the stream was successfully retrieves
+ *   and parsed, and %FALSE otherwise. In case of error, the #GError will be
+ *   filled accordingly.
+ *
+ * Since: 0.12
+ */
+gboolean
+json_parser_load_from_stream_finish (JsonParser    *parser,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+  GSimpleAsyncResult *simple;
+  LoadStreamData *data;
+
+  g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+  g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+  simple = G_SIMPLE_ASYNC_RESULT (result);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    return FALSE;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == json_parser_load_from_stream_async);
+
+  data = g_simple_async_result_get_op_res_gpointer (simple);
+
+  if (data->error)
+    {
+      g_propagate_error (error, data->error);
+      data->error = NULL;
+      return FALSE;
+    }
+
+  g_byte_array_set_size (data->content, data->pos + 1);
+  data->content->data[data->pos] = 0;
+
+  return json_parser_load (parser, (const gchar *) data->content->data, data->content->len, error);
+}
+
+/**
+ * json_parser_load_from_stream_async:
+ * @parser: a #JsonParser
+ * @stream: a #GInputStream
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to @callback
+ *
+ * Asynchronously reads the contents of @stream.
+ *
+ * For more details, see json_parser_load_from_stream() which is the
+ * synchronous version of this call.
+ *
+ * When the operation is finished, @callback will be called. You should
+ * then call json_parser_load_from_stream_finish() to get the result
+ * of the operation.
+ *
+ * Since: 0.12
+ */
+void
+json_parser_load_from_stream_async (JsonParser          *parser,
+                                    GInputStream        *stream,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+  LoadStreamData *data;
+
+  g_return_if_fail (JSON_IS_PARSER (parser));
+  g_return_if_fail (G_IS_INPUT_STREAM (stream));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+  data = g_new0 (LoadStreamData, 1);
+
+  if (cancellable != NULL)
+    data->cancellable = g_object_ref (cancellable);
+
+  data->callback = callback;
+  data->user_data = user_data;
+  data->content = g_byte_array_new ();
+  data->parser = g_object_ref (parser);
+
+  g_byte_array_set_size (data->content, data->pos + GET_DATA_BLOCK_SIZE);
+  g_input_stream_read_async (stream, data->content->data + data->pos,
+                             GET_DATA_BLOCK_SIZE, 0,
+                             data->cancellable,
+                             load_stream_data_read_callback,
+                             data);
+}
diff --git a/src/glib-jsonrpc/json-glib/json-parser.h b/src/glib-jsonrpc/json-glib/json-parser.h
new file mode 100644
index 0000000..36107f4
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-parser.h
@@ -0,0 +1,173 @@
+/* json-parser.h - JSON streams parser
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_PARSER_H__
+#define __JSON_PARSER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <json-glib/json-types.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_PARSER                (json_parser_get_type ())
+#define JSON_PARSER(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_PARSER, JsonParser))
+#define JSON_IS_PARSER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_PARSER))
+#define JSON_PARSER_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), JSON_TYPE_PARSER, JsonParserClass))
+#define JSON_IS_PARSER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), JSON_TYPE_PARSER))
+#define JSON_PARSER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), JSON_TYPE_PARSER, JsonParserClass))
+
+#define JSON_PARSER_ERROR               (json_parser_error_quark ())
+
+typedef struct _JsonParser              JsonParser;
+typedef struct _JsonParserPrivate       JsonParserPrivate;
+typedef struct _JsonParserClass         JsonParserClass;
+
+/**
+ * JsonParserError:
+ * @JSON_PARSER_ERROR_PARSE: parse error
+ * @JSON_PARSER_ERROR_TRAILING_COMMA: unexpected trailing comma
+ * @JSON_PARSER_ERROR_MISSING_COMMA: expected comma
+ * @JSON_PARSER_ERROR_MISSING_COLON: expected colon
+ * @JSON_PARSER_ERROR_INVALID_BAREWORD: invalid bareword
+ * @JSON_PARSER_ERROR_UNKNOWN: unknown error
+ *
+ * Error enumeration for #JsonParser
+ *
+ * This enumeration can be extended at later date
+ */
+typedef enum {
+  JSON_PARSER_ERROR_PARSE,
+  JSON_PARSER_ERROR_TRAILING_COMMA,
+  JSON_PARSER_ERROR_MISSING_COMMA,
+  JSON_PARSER_ERROR_MISSING_COLON,
+  JSON_PARSER_ERROR_INVALID_BAREWORD,
+  
+  JSON_PARSER_ERROR_UNKNOWN
+} JsonParserError;
+
+/**
+ * JsonParser:
+ * 
+ * JSON data streams parser. The contents of the #JsonParser structure are
+ * private and should only be accessed via the provided API.
+ */
+struct _JsonParser
+{
+  /*< private >*/
+  GObject parent_instance;
+
+  JsonParserPrivate *priv;
+};
+
+/**
+ * JsonParserClass:
+ * @parse_start: class handler for the JsonParser::parse-start signal
+ * @object_start: class handler for the JsonParser::object-start signal
+ * @object_member: class handler for the JsonParser::object-member signal
+ * @object_end: class handler for the JsonParser::object-end signal
+ * @array_start: class handler for the JsonParser::array-start signal
+ * @array_element: class handler for the JsonParser::array-element signal
+ * @array_end: class handler for the JsonParser::array-end signal
+ * @parse_end: class handler for the JsonParser::parse-end signal
+ * @error: class handler for the JsonParser::error signal
+ *
+ * #JsonParser class.
+ */
+struct _JsonParserClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  /*< public  >*/
+  void (* parse_start)   (JsonParser   *parser);
+
+  void (* object_start)  (JsonParser   *parser);
+  void (* object_member) (JsonParser   *parser,
+                          JsonObject   *object,
+                          const gchar  *member_name);
+  void (* object_end)    (JsonParser   *parser,
+                          JsonObject   *object);
+
+  void (* array_start)   (JsonParser   *parser);
+  void (* array_element) (JsonParser   *parser,
+                          JsonArray    *array,
+                          gint          index_);
+  void (* array_end)     (JsonParser   *parser,
+                          JsonArray    *array);
+
+  void (* parse_end)     (JsonParser   *parser);
+  
+  void (* error)         (JsonParser   *parser,
+                          const GError *error);
+
+  /*< private >*/
+  /* padding for future expansion */
+  void (* _json_reserved1) (void);
+  void (* _json_reserved2) (void);
+  void (* _json_reserved3) (void);
+  void (* _json_reserved4) (void);
+  void (* _json_reserved5) (void);
+  void (* _json_reserved6) (void);
+  void (* _json_reserved7) (void);
+  void (* _json_reserved8) (void);
+};
+
+GQuark json_parser_error_quark (void);
+GType json_parser_get_type (void) G_GNUC_CONST;
+
+JsonParser *json_parser_new                     (void);
+gboolean    json_parser_load_from_file          (JsonParser           *parser,
+                                                 const gchar          *filename,
+                                                 GError              **error);
+gboolean    json_parser_load_from_data          (JsonParser           *parser,
+                                                 const gchar          *data,
+                                                 gssize                length,
+                                                 GError              **error);
+gboolean    json_parser_load_from_stream        (JsonParser           *parser,
+                                                 GInputStream         *stream,
+                                                 GCancellable         *cancellable,
+                                                 GError              **error);
+void        json_parser_load_from_stream_async  (JsonParser           *parser,
+                                                 GInputStream         *stream,
+                                                 GCancellable         *cancellable,
+                                                 GAsyncReadyCallback   callback,
+                                                 gpointer              user_data);
+gboolean    json_parser_load_from_stream_finish (JsonParser           *parser,
+                                                 GAsyncResult         *result,
+                                                 GError              **error);
+
+JsonNode *  json_parser_get_root                (JsonParser           *parser);
+
+guint       json_parser_get_current_line        (JsonParser           *parser);
+guint       json_parser_get_current_pos         (JsonParser           *parser);
+gboolean    json_parser_has_assignment          (JsonParser           *parser,
+                                                 gchar               **variable_name);
+
+G_END_DECLS
+
+#endif /* __JSON_PARSER_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-path.c b/src/glib-jsonrpc/json-glib/json-path.c
new file mode 100644
index 0000000..09d9543
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-path.c
@@ -0,0 +1,1033 @@
+/* json-path.h - JSONPath implementation
+ *
+ * This file is part of JSON-GLib
+ * Copyright  2011  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:json-path
+ * @Title: JsonPath
+ * @short_description: JSONPath implementation
+ *
+ * #JsonPath is a simple class implementing the JSONPath syntax for extracting
+ * data out of a JSON tree. While the semantics of the JSONPath expressions are
+ * heavily borrowed by the XPath specification for XML, the syntax follows the
+ * ECMAScript origins of JSON.
+ *
+ * Once a #JsonPath instance has been created, it has to compile a JSONPath
+ * expression using json_path_compile() before being able to match it to a
+ * JSON tree; the same #JsonPath instance can be used to match multiple JSON
+ * trees. It it also possible to compile a new JSONPath expression using the
+ * same #JsonPath instance; the previous expression will be discarded only if
+ * the compilation of the new expression is successful.
+ *
+ * The simple convenience function json_path_query() can be used for one-off
+ * matching.
+ *
+ * <refsect2 id="json-path-syntax">
+ *   <title>Syntax of the JSONPath expressions</title>
+ *   <para>A JSONPath expression is composed by path indices and operators.
+ *   Each path index can either be a member name or an element index inside
+ *   a JSON tree. A JSONPath expression must start with the '$' operator; each
+ *   path index is separated using either the dot notation or the bracket
+ *   notation, e.g.:</para>
+ *   |[
+ *     /&ast; dot notation &ast;/
+ *     $.store.book[0].title
+ *     /&ast; bracket notation &ast;/
+ *     $['store']['book'][0]['title']
+ *   ]|
+ *   <para>The available operators are:</para>
+ *   <table frame='all' id="json-path-operators">
+ *     <title>Operators</title>
+ *     <tgroup cols='4'>
+ *       <colspec name='operator'/>
+ *       <colspec name='description'/>
+ *       <colspec name='example'/>
+ *       <colspec name='results'/>
+ *       <thead>
+ *         <row>
+ *           <entry>Operator</entry>
+ *           <entry>Description</entry>
+ *           <entry>Example</entry>
+ *           <entry>Results</entry>
+ *         </row>
+ *       </thead>
+ *       <tbody>
+ *         <row>
+ *           <entry>$</entry>
+ *           <entry>The root node</entry>
+ *           <entry>$</entry>
+ *           <entry>The whole document</entry>
+ *         </row>
+ *         <row>
+ *           <entry>. or []</entry>
+ *           <entry>The child member or element</entry>
+ *           <entry>$.store.book</entry>
+ *           <entry>The contents of the book member of the store object</entry>
+ *         </row>
+ *         <row>
+ *           <entry>..</entry>
+ *           <entry>Recursive descent</entry>
+ *           <entry>$..author</entry>
+ *           <entry>The content of the author member in every object</entry>
+ *         </row>
+ *         <row>
+ *           <entry>*</entry>
+ *           <entry>Wildcard</entry>
+ *           <entry>$.store.book[*].author</entry>
+ *           <entry>The content of the author member of any object of the
+ *           array contained in the book member of the store object</entry>
+ *         </row>
+ *         <row>
+ *           <entry>[]</entry>
+ *           <entry>Subscript</entry>
+ *           <entry>$.store.book[0]</entry>
+ *           <entry>The first element of the array contained in the book
+ *           member of the store object</entry>
+ *         </row>
+ *         <row>
+ *           <entry>[,]</entry>
+ *           <entry>Set</entry>
+ *           <entry>$.store.book[0,1]</entry>
+ *           <entry>The first two elements of the array contained in the
+ *           book member of the store object</entry>
+ *         </row>
+ *         <row>
+ *           <entry>[start:end:step]</entry>
+ *           <entry>Slice</entry>
+ *           <entry>$.store.book[:2]</entry>
+ *           <entry>The first two elements of the array contained in the
+ *           book member of the store object; the start and step are omitted
+ *           and implied to be 0 and 1, respectively</entry>
+ *         </row>
+ *       </tbody>
+ *     </tgroup>
+ *   </table>
+ *   <para>More information about JSONPath is available on Stefan GÃssner's
+ *   <ulink url="http://goessner.net/articles/JsonPath/";>website</ulink>.</para>
+ * </refsect2>
+ *
+ * <example id="json-path-example">
+ *   <title>Example of JsonPath usage</title>
+ *   <para>The following example shows some of the results of using #JsonPath
+ *   on a JSON tree. We use the following JSON description of a
+ *   bookstore:</para>
+ * <programlisting><![CDATA[
+{ "store": {
+    "book": [
+      { "category": "reference",
+        "author": "Nigel Rees",
+        "title": "Sayings of the Century",
+        "price": "8.95"
+      },
+      { "category": "fiction",
+        "author": "Evelyn Waugh",
+        "title": "Sword of Honour",
+        "price": "12.99"
+      },
+      { "category": "fiction",
+        "author": "Herman Melville",
+        "title": "Moby Dick",
+        "isbn": "0-553-21311-3",
+        "price": "8.99"
+      },
+      { "category": "fiction",
+        "author": "J. R. R. Tolkien",
+        "title": "The Lord of the Rings",
+        "isbn": "0-395-19395-8",
+        "price": "22.99"
+      }
+    ],
+    "bicycle": {
+      "color": "red",
+      "price": "19.95"
+    }
+  }
+}
+]]></programlisting>
+ *   <para>We can parse the JSON using #JsonParser:</para>
+ *   <programlisting>
+ * JsonParser *parser = json_parser_new ();
+ * json_parser_load_from_data (parser, json_data, -1, NULL);
+ *   </programlisting>
+ *   <para>If we run the following code:</para>
+ *   <programlisting>
+ * JsonNode *result;
+ * JsonPath *path = json_path_new ();
+ * json_path_compile (path, "$.store..author", NULL);
+ * result = json_path_match (path, json_parser_get_root (parser));
+ *   </programlisting>
+ *   <para>The <emphasis>result</emphasis> #JsonNode will contain an array
+ *   with all values of the <emphasis>author</emphasis> member of the objects
+ *   in the JSON tree. If we use a #JsonGenerator to convert the #JsonNode
+ *   to a string and print it:</para>
+ *   <programlisting>
+ * JsonGenerator *generator = json_generator_new ();
+ * char *str;
+ * json_generator_set_pretty (generator, TRUE);
+ * json_generator_set_root (generator, result);
+ * str = json_generator_to_data (generator, NULL);
+ * g_print ("Results: %s\n", str);
+ *   </programlisting>
+ *   <para>The output will be:</para>
+ *   <programlisting><![CDATA[
+[
+  "Nigel Rees",
+  "Evelyn Waugh",
+  "Herman Melville",
+  "J. R. R. Tolkien"
+]
+]]></programlisting>
+ * </example>
+ *
+ * #JsonPath is available since JSON-GLib 0.14
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#if 0
+#include <glib/gi18n-lib.h>
+#else
+#define _(s) s
+#endif
+
+#include "json-path.h"
+
+#include "json-debug.h"
+#include "json-types-private.h"
+
+typedef enum {
+  JSON_PATH_NODE_ROOT,
+  JSON_PATH_NODE_CHILD_MEMBER,
+  JSON_PATH_NODE_CHILD_ELEMENT,
+  JSON_PATH_NODE_RECURSIVE_DESCENT,
+  JSON_PATH_NODE_WILDCARD_MEMBER,
+  JSON_PATH_NODE_WILDCARD_ELEMENT,
+  JSON_PATH_NODE_ELEMENT_SET,
+  JSON_PATH_NODE_ELEMENT_SLICE
+} PathNodeType;
+
+typedef struct _PathNode        PathNode;
+
+struct _JsonPath
+{
+  GObject parent_instance;
+
+  /* the compiled path */
+  GList *nodes;
+
+  guint is_compiled : 1;
+};
+
+struct _JsonPathClass
+{
+  GObjectClass parent_class;
+};
+
+struct _PathNode
+{
+  PathNodeType node_type;
+
+  union {
+    /* JSON_PATH_NODE_CHILD_ELEMENT */
+    int element_index;
+
+    /* JSON_PATH_NODE_CHILD_MEMBER */
+    char *member_name;
+
+    /* JSON_PATH_NODE_ELEMENT_SET */
+    struct { int n_indices; int *indices; } set;
+
+    /* JSON_PATH_NODE_ELEMENT_SLICE */
+    struct { int start, end, step; } slice;
+  } data;
+};
+
+G_DEFINE_TYPE (JsonPath, json_path, G_TYPE_OBJECT)
+
+static void
+path_node_free (gpointer data)
+{
+  if (data != NULL)
+    {
+      PathNode *node = data;
+
+      switch (node->node_type)
+        {
+        case JSON_PATH_NODE_CHILD_MEMBER:
+          g_free (node->data.member_name);
+          break;
+
+        case JSON_PATH_NODE_ELEMENT_SET:
+          g_free (node->data.set.indices);
+          break;
+
+        default:
+          break;
+        }
+
+      g_free (node);
+    }
+}
+
+static void
+json_path_finalize (GObject *gobject)
+{
+  JsonPath *self = JSON_PATH (gobject);
+
+  g_list_free_full (self->nodes, path_node_free);
+
+  G_OBJECT_CLASS (json_path_parent_class)->finalize (gobject);
+}
+
+static void
+json_path_class_init (JsonPathClass *klass)
+{
+  G_OBJECT_CLASS (klass)->finalize = json_path_finalize;
+}
+
+static void
+json_path_init (JsonPath *self)
+{
+}
+
+GQuark
+json_path_error_quark (void)
+{
+  return g_quark_from_static_string ("json-path-error");
+}
+
+/**
+ * json_path_new:
+ *
+ * Creates a new #JsonPath instance.
+ *
+ * Once created, the #JsonPath object should be used with json_path_compile()
+ * and json_path_match().
+ *
+ * Return value: (transfer full): the newly created #JsonPath instance. Use
+ *   g_object_unref() to free the allocated resources when done
+ *
+ * Since: 0.14
+ */
+JsonPath *
+json_path_new (void)
+{
+  return g_object_new (JSON_TYPE_PATH, NULL);
+}
+
+/**
+ * json_path_compile:
+ * @path: a #JsonPath
+ * @expression: a JSONPath expression
+ * @error: return location for a #GError, or %NULL
+ *
+ * Validates and decomposes @expression.
+ *
+ * A JSONPath expression must be compiled before calling json_path_match().
+ *
+ * Return value: %TRUE on success; on error, @error will be set with
+ *   the %JSON_PATH_ERROR domain and a code from the #JsonPathError
+ *   enumeration, and %FALSE will be returned
+ *
+ * Since: 0.14
+ */
+gboolean
+json_path_compile (JsonPath    *path,
+                   const char  *expression,
+                   GError     **error)
+{
+  const char *p, *end_p;
+  PathNode *root = NULL;
+  GList *nodes, *l;
+
+  p = expression;
+
+  while (*p != '\0')
+    {
+      switch (*p)
+        {
+        case '$':
+          {
+            PathNode *node;
+
+            if (root != NULL)
+              {
+                g_set_error_literal (error, JSON_PATH_ERROR,
+                                     JSON_PATH_ERROR_INVALID_QUERY,
+                                     _("Only one root node is allowed in a JSONPath expression"));
+                return FALSE;
+              }
+
+            if (!(*(p + 1) == '.' || *(p + 1) == '['))
+              {
+                /* translators: the %c is the invalid character */
+                g_set_error (error, JSON_PATH_ERROR,
+                             JSON_PATH_ERROR_INVALID_QUERY,
+                             _("Root node followed by invalid character '%c'"),
+                             *(p + 1));
+                return FALSE;
+              }
+            
+            node = g_new0 (PathNode, 1);
+            node->node_type = JSON_PATH_NODE_ROOT;
+
+            root = node;
+            nodes = g_list_prepend (NULL, root);
+          }
+          break;
+
+        case '.':
+        case '[':
+          {
+            PathNode *node = NULL;
+
+            if (*p == '.' && *(p + 1) == '.')
+              {
+                node = g_new0 (PathNode, 1);
+                node->node_type = JSON_PATH_NODE_RECURSIVE_DESCENT;
+              }
+            else if (*p == '.' && *(p + 1) == '*')
+              {
+                node = g_new0 (PathNode, 1);
+                node->node_type = JSON_PATH_NODE_WILDCARD_MEMBER;
+
+                p += 1;
+              }
+            else if (*p == '.')
+              {
+                end_p = p + 1;
+                while (!(*end_p == '.' || *end_p == '[' || *end_p == '\0'))
+                  end_p += 1;
+
+                node = g_new0 (PathNode, 1);
+                node->node_type = JSON_PATH_NODE_CHILD_MEMBER;
+                node->data.member_name = g_strndup (p + 1, end_p - p - 1);
+
+                p = end_p - 1;
+              }
+            else if (*p == '[' && *(p + 1) == '\'')
+              {
+                if (*(p + 2) == '*' && *(p + 3) == '\'' && *(p + 4) == ']')
+                  {
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_WILDCARD_MEMBER;
+
+                    p += 4;
+                  }
+                else
+                  {
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_CHILD_MEMBER;
+
+                    end_p = strchr (p + 2, '\'');
+                    node->data.member_name = g_strndup (p + 2, end_p - p - 2);
+
+                    p = end_p + 1;
+                  }
+              }
+            else if (*p == '[' && *(p + 1) == '*' && *(p + 2) == ']')
+              {
+                node = g_new0 (PathNode, 1);
+                node->node_type = JSON_PATH_NODE_WILDCARD_ELEMENT;
+
+                p += 1;
+              }
+            else if (*p == '[')
+              {
+                int sign = 1;
+                int idx;
+
+                end_p = p + 1;
+
+                if (*end_p == '-')
+                  {
+                    sign = -1;
+                    end_p += 1;
+                  }
+
+                /* slice with missing start */
+                if (*end_p == ':')
+                  {
+                    int slice_end = g_ascii_strtoll (end_p + 1, (char **) &end_p, 10) * sign;
+                    int slice_step = 1;
+
+                    if (*end_p == ':')
+                      {
+                        end_p += 1;
+
+                        if (*end_p == '-')
+                          {
+                            sign = -1;
+                            end_p += 1;
+                          }
+                        else
+                          sign = 1;
+
+                        slice_step = g_ascii_strtoll (end_p, (char **) &end_p, 10) * sign;
+
+                        if (*end_p != ']')
+                          {
+                            g_set_error (error, JSON_PATH_ERROR,
+                                         JSON_PATH_ERROR_INVALID_QUERY,
+                                         _("Malformed slice expression '%*s'"),
+                                         end_p - p,
+                                         p + 1);
+                            goto fail;
+                          }
+                      }
+
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_ELEMENT_SLICE;
+                    node->data.slice.start = 0;
+                    node->data.slice.end = slice_end;
+                    node->data.slice.step = slice_step;
+
+                    nodes = g_list_prepend (nodes, node);
+                    p = end_p;
+                    break;
+                  }
+
+                idx = g_ascii_strtoll (end_p, (char **) &end_p, 10) * sign;
+
+                if (*end_p == ',')
+                  {
+                    GArray *indices = g_array_new (FALSE, TRUE, sizeof (int));
+
+                    g_array_append_val (indices, idx);
+
+                    while (*end_p != ']')
+                      {
+                        end_p += 1;
+
+                        if (*end_p == '-')
+                          {
+                            sign = -1;
+                            end_p += 1;
+                          }
+                        else
+                          sign = 1;
+
+                        idx = g_ascii_strtoll (end_p, (char **) &end_p, 10) * sign;
+                        if (!(*end_p == ',' || *end_p == ']'))
+                          {
+                            g_array_unref (indices);
+                            g_set_error (error, JSON_PATH_ERROR,
+                                         JSON_PATH_ERROR_INVALID_QUERY,
+                                         _("Invalid set definition '%*s'"),
+                                         end_p - p,
+                                         p + 1);
+                            goto fail;
+                          }
+
+                        g_array_append_val (indices, idx);
+                      }
+
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_ELEMENT_SET;
+                    node->data.set.n_indices =  indices->len;
+                    node->data.set.indices = (int *) g_array_free (indices, FALSE);
+                    nodes = g_list_prepend (nodes, node);
+                    p = end_p;
+                    break;
+                  }
+                else if (*end_p == ':')
+                  {
+                    int slice_start = idx;
+                    int slice_end = 0;
+                    int slice_step = 1;
+
+                    end_p += 1;
+
+                    if (*end_p == '-')
+                      {
+                        sign = -1;
+                        end_p += 1;
+                      }
+                    else
+                      sign = 1;
+
+                    slice_end = g_ascii_strtoll (end_p, (char **) &end_p, 10) * sign;
+                    if (*end_p == ':')
+                      {
+                        end_p += 1;
+
+                        if (*end_p == '-')
+                          {
+                            sign = -1;
+                            end_p += 1;
+                          }
+                        else
+                          sign = 1;
+
+                        slice_step = g_ascii_strtoll (end_p + 1, (char **) &end_p, 10) * sign;
+                      }
+
+                    if (*end_p != ']')
+                      {
+                        g_set_error (error, JSON_PATH_ERROR,
+                                     JSON_PATH_ERROR_INVALID_QUERY,
+                                     _("Invalid slice definition '%*s'"),
+                                     end_p - p,
+                                     p + 1);
+                        goto fail;
+                      }
+
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_ELEMENT_SLICE;
+                    node->data.slice.start = slice_start;
+                    node->data.slice.end = slice_end;
+                    node->data.slice.step = slice_step;
+                    nodes = g_list_prepend (nodes, node);
+                    p = end_p;
+                    break;
+                  }
+                else if (*end_p == ']')
+                  {
+                    node = g_new0 (PathNode, 1);
+                    node->node_type = JSON_PATH_NODE_CHILD_ELEMENT;
+                    node->data.element_index = idx;
+                    nodes = g_list_prepend (nodes, node);
+                    p = end_p;
+                    break;
+                  }
+                else
+                  {
+                    g_set_error (error, JSON_PATH_ERROR,
+                                 JSON_PATH_ERROR_INVALID_QUERY,
+                                 _("Invalid array index definition '%*s'"),
+                                 end_p - p,
+                                 p + 1);
+                    goto fail;
+                  }
+              }
+            else
+              break;
+
+            if (node != NULL)
+              nodes = g_list_prepend (nodes, node);
+          }
+          break;
+
+        default:
+          break;
+        }
+
+      p += 1;
+    }
+
+  nodes = g_list_reverse (nodes);
+
+#ifdef JSON_ENABLE_DEBUG
+  if (_json_get_debug_flags () & JSON_DEBUG_PATH)
+    {
+      GString *buf = g_string_new (NULL);
+
+      for (l = nodes; l != NULL; l = l->next)
+        {
+          PathNode *cur_node = l->data;
+
+          switch (cur_node->node_type)
+            {
+            case JSON_PATH_NODE_ROOT:
+              g_string_append (buf, "<root");
+              break;
+
+            case JSON_PATH_NODE_CHILD_MEMBER:
+              g_string_append_printf (buf, "<member '%s'", cur_node->data.member_name);
+              break;
+
+            case JSON_PATH_NODE_CHILD_ELEMENT:
+              g_string_append_printf (buf, "<element '%d'", cur_node->data.element_index);
+              break;
+
+            case JSON_PATH_NODE_RECURSIVE_DESCENT:
+              g_string_append (buf, "<recursive descent");
+              break;
+
+            case JSON_PATH_NODE_WILDCARD_MEMBER:
+              g_string_append (buf, "<wildcard member");
+              break;
+
+            case JSON_PATH_NODE_WILDCARD_ELEMENT:
+              g_string_append (buf, "<wildcard element");
+              break;
+
+            case JSON_PATH_NODE_ELEMENT_SET:
+              {
+                int i;
+
+                g_string_append (buf, "<element set ");
+                for (i = 0; i < cur_node->data.set.n_indices - 1; i++)
+                  g_string_append_printf (buf, "'%d', ", cur_node->data.set.indices[i]);
+
+                g_string_append_printf (buf, "'%d'", cur_node->data.set.indices[i]);
+              }
+              break;
+
+            case JSON_PATH_NODE_ELEMENT_SLICE:
+              g_string_append_printf (buf, "<slice start '%d', end '%d', step '%d'",
+                                      cur_node->data.slice.start,
+                                      cur_node->data.slice.end,
+                                      cur_node->data.slice.step);
+              break;
+
+            default:
+              g_string_append (buf, "<unknown node");
+              break;
+            }
+
+          if (l->next != NULL)
+            g_string_append (buf, ">, ");
+          else
+            g_string_append (buf, ">");
+        }
+
+      g_message ("[PATH] " G_STRLOC ": expression '%s' => '%s'", expression, buf->str);
+      g_string_free (buf, TRUE);
+    }
+#endif /* JSON_ENABLE_DEBUG */
+
+  if (path->nodes != NULL)
+    g_list_free_full (path->nodes, path_node_free);
+
+  path->nodes = nodes;
+  path->is_compiled = (path->nodes != NULL);
+
+  return path->nodes != NULL;
+
+fail:
+  g_list_free_full (nodes, path_node_free);
+
+  return FALSE;
+}
+
+static void
+walk_path_node (GList      *path,
+                JsonNode   *root,
+                JsonArray  *results)
+{
+  PathNode *node = path->data;
+
+  switch (node->node_type)
+    {
+    case JSON_PATH_NODE_ROOT:
+      walk_path_node (path->next, root, results);
+      break;
+
+    case JSON_PATH_NODE_CHILD_MEMBER:
+      if (JSON_NODE_HOLDS_OBJECT (root))
+        {
+          JsonObject *object = json_node_get_object (root);
+
+          if (json_object_has_member (object, node->data.member_name))
+            {
+              JsonNode *member = json_object_get_member (object, node->data.member_name);
+              
+              if (path->next == NULL)
+                {
+                  JSON_NOTE (PATH, "end of path at member '%s'", node->data.member_name);
+                  json_array_add_element (results, json_node_copy (member));
+                }
+              else
+                walk_path_node (path->next, member, results);
+            }
+        }
+      break;
+
+    case JSON_PATH_NODE_CHILD_ELEMENT:
+      if (JSON_NODE_HOLDS_ARRAY (root))
+        {
+          JsonArray *array = json_node_get_array (root);
+
+          if (json_array_get_length (array) >= node->data.element_index)
+            {
+              JsonNode *element = json_array_get_element (array, node->data.element_index);
+
+              if (path->next == NULL)
+                {
+                  JSON_NOTE (PATH, "end of path at element '%d'", node->data.element_index);
+                  json_array_add_element (results, json_node_copy (element));
+                }
+              else
+                walk_path_node (path->next, element, results);
+            }
+        }
+      break;
+
+    case JSON_PATH_NODE_RECURSIVE_DESCENT:
+      {
+        PathNode *tmp = path->next->data;
+
+        switch (json_node_get_node_type (root))
+          {
+          case JSON_NODE_OBJECT:
+            {
+              JsonObject *object = json_node_get_object (root);
+              GList *members, *l;
+
+              members = json_object_get_members (object);
+              for (l = members; l != NULL; l = l->next)
+                {
+                  JsonNode *m = json_object_get_member (object, l->data);
+
+                  if (tmp->node_type == JSON_PATH_NODE_CHILD_MEMBER &&
+                      strcmp (tmp->data.member_name, l->data) == 0)
+                    {
+                      JSON_NOTE (PATH, "entering '%s'", tmp->data.member_name);
+                      walk_path_node (path->next, root, results);
+                    }
+                  else
+                    {
+                      JSON_NOTE (PATH, "recursing into '%s'", (char *) l->data);
+                      walk_path_node (path, m, results);
+                    }
+                }
+              g_list_free (members);
+            }
+            break;
+
+          case JSON_NODE_ARRAY:
+            {
+              JsonArray *array = json_node_get_array (root);
+              GList *members, *l;
+              int i;
+
+              members = json_array_get_elements (array);
+              for (l = members, i = 0; l != NULL; l = l->next, i += 1)
+                {
+                  JsonNode *m = l->data;
+
+                  if (tmp->node_type == JSON_PATH_NODE_CHILD_ELEMENT &&
+                      tmp->data.element_index == i)
+                    {
+                      JSON_NOTE (PATH, "entering '%d'", tmp->data.element_index);
+                      walk_path_node (path->next, root, results);
+                    }
+                  else
+                    {
+                      JSON_NOTE (PATH, "recursing into '%d'", i);
+                      walk_path_node (path, m, results);
+                    }
+                }
+              g_list_free (members);
+            }
+            break;
+
+          default:
+            break;
+          }
+      }
+      break;
+
+    case JSON_PATH_NODE_WILDCARD_MEMBER:
+      if (JSON_NODE_HOLDS_OBJECT (root))
+        {
+          JsonObject *object = json_node_get_object (root);
+          GList *members, *l;
+
+          members = json_object_get_members (object);
+          for (l = members; l != NULL; l = l->next)
+            {
+              JsonNode *member = json_object_get_member (object, l->data);
+
+              if (path->next != NULL)
+                walk_path_node (path->next, member, results);
+              else
+                {
+                  JSON_NOTE (PATH, "glob match member '%s'", (char *) l->data);
+                  json_array_add_element (results, json_node_copy (root));
+                }
+            }
+          g_list_free (members);
+        }
+      else
+        json_array_add_element (results, json_node_copy (root));
+      break;
+
+    case JSON_PATH_NODE_WILDCARD_ELEMENT:
+      if (JSON_NODE_HOLDS_ARRAY (root))
+        {
+          JsonArray *array = json_node_get_array (root);
+          GList *elements, *l;
+          int i;
+
+          elements = json_array_get_elements (array);
+          for (l = elements, i = 0; l != NULL; l = l->next, i += 1)
+            {
+              JsonNode *element = l->data;
+
+              if (path->next != NULL)
+                walk_path_node (path->next, element, results);
+              else
+                {
+                  JSON_NOTE (PATH, "glob match element '%d'", i);
+                  json_array_add_element (results, json_node_copy (root));
+                }
+            }
+          g_list_free (elements);
+        }
+      else
+        json_array_add_element (results, json_node_copy (root));
+      break;
+
+    case JSON_PATH_NODE_ELEMENT_SET:
+      if (JSON_NODE_HOLDS_ARRAY (root))
+        {
+          JsonArray *array = json_node_get_array (root);
+          int i;
+
+          for (i = 0; i < node->data.set.n_indices; i += 1)
+            {
+              int idx = node->data.set.indices[i];
+              JsonNode *element = json_array_get_element (array, idx);
+
+              if (path->next != NULL)
+                walk_path_node (path->next, element, results);
+              else
+                {
+                  JSON_NOTE (PATH, "set element '%d'", idx);
+                  json_array_add_element (results, json_node_copy (element));
+                }
+            }
+        }
+      break;
+
+    case JSON_PATH_NODE_ELEMENT_SLICE:
+      if (JSON_NODE_HOLDS_ARRAY (root))
+        {
+          JsonArray *array = json_node_get_array (root);
+          int i, start, end;
+
+          if (node->data.slice.start < 0)
+            {
+              start = json_array_get_length (array)
+                    + node->data.slice.start;
+
+              end = json_array_get_length (array)
+                  + node->data.slice.end;
+            }
+          else
+            {
+              start = node->data.slice.start;
+              end = node->data.slice.end;
+            }
+
+          for (i = start; i < end; i += node->data.slice.step)
+            {
+              JsonNode *element = json_array_get_element (array, i);
+
+              if (path->next != NULL)
+                walk_path_node (path->next, element, results);
+              else
+                {
+                  JSON_NOTE (PATH, "slice element '%d'", i);
+                  json_array_add_element (results, json_node_copy (element));
+                }
+            }
+        }
+      break;
+
+    default:
+      break;
+    }
+}
+
+/**
+ * json_path_match:
+ * @path: a compiled #JsonPath
+ * @root: a #JsonNode
+ *
+ * Matches the JSON tree pointed by @root using the expression compiled
+ * into the #JsonPath.
+ *
+ * The matching #JsonNode<!-- -->s will be copied into a #JsonArray and
+ * returned wrapped in a #JsonNode.
+ *
+ * Return value: (transfer full): a newly-created #JsonNode of type
+ *   %JSON_NODE_ARRAY containing an array of matching #JsonNode<!-- -->s.
+ *   Use json_node_free() when done
+ *
+ * Since: 0.14
+ */
+JsonNode *
+json_path_match (JsonPath *path,
+                 JsonNode *root)
+{
+  JsonArray *results;
+  JsonNode *retval;
+
+  g_return_val_if_fail (JSON_IS_PATH (path), NULL);
+  g_return_val_if_fail (path->is_compiled, NULL);
+  g_return_val_if_fail (root != NULL, NULL);
+
+  results = json_array_new ();
+
+  walk_path_node (path->nodes, root, results);
+
+  retval = json_node_new (JSON_NODE_ARRAY);
+  json_node_take_array (retval, results);
+
+  return retval;
+}
+
+/**
+ * json_path_query:
+ * @expression: a JSONPath expression
+ * @root: the root of a JSON tree
+ * @error: return location for a #GError, or %NULL
+ *
+ * Queries a JSON tree using a JSONPath expression.
+ *
+ * This function is a simple wrapper around json_path_new(),
+ * json_path_compile() and json_path_match(). It implicitly
+ * creates a #JsonPath instance, compiles @expression and
+ * matches it against the JSON tree pointed by @root.
+ *
+ * Return value: (transfer full): a newly-created #JsonNode of type
+ *   %JSON_NODE_ARRAY containing an array of matching #JsonNode<!-- -->s.
+ *   Use json_node_free() when done
+ *
+ * Since: 0.14
+ */
+JsonNode *
+json_path_query (const char  *expression,
+                 JsonNode    *root,
+                 GError     **error)
+{
+  JsonPath *path = json_path_new ();
+  JsonNode *retval;
+
+  if (!json_path_compile (path, expression, error))
+    {
+      g_object_unref (path);
+      return NULL;
+    }
+
+  retval = json_path_match (path, root);
+
+  g_object_unref (path);
+
+  return retval;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-path.h b/src/glib-jsonrpc/json-glib/json-path.h
new file mode 100644
index 0000000..2bae608
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-path.h
@@ -0,0 +1,97 @@
+/* json-path.h - JSONPath implementation
+ *
+ * This file is part of JSON-GLib
+ * Copyright  2011  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_PATH_H__
+#define __JSON_PATH_H__
+
+#include <json-glib/json-types.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_PATH          (json_path_get_type ())
+#define JSON_PATH(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_PATH, JsonPath))
+#define JSON_IS_PATH(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_PATH))
+
+/**
+ * JSON_PATH_ERROR:
+ *
+ * Error domain for #JsonPath errors
+ *
+ * Since: 0.14
+ */
+#define JSON_PATH_ERROR         (json_path_error_quark ())
+
+/**
+ * JsonPathError:
+ * @JSON_PATH_ERROR_INVALID_QUERY: Invalid query
+ *
+ * Error code enumeration for the %JSON_PATH_ERROR domain.
+ *
+ * Since: 0.14
+ */
+typedef enum {
+  JSON_PATH_ERROR_INVALID_QUERY
+} JsonPathError;
+
+/**
+ * JsonPath:
+ *
+ * The <structname>JsonPath</structname> structure is an opaque object
+ * whose members cannot be directly accessed except through the provided
+ * API.
+ *
+ * Since: 0.14
+ */
+typedef struct _JsonPath        JsonPath;
+
+/**
+ * JsonPathClass:
+ *
+ * The <structname>JsonPathClass</structname> structure is an opaque
+ * object class whose members cannot be directly accessed.
+ *
+ * Since: 0.14
+ */
+typedef struct _JsonPathClass   JsonPathClass;
+
+GType json_path_get_type (void) G_GNUC_CONST;
+GQuark json_path_error_quark (void);
+
+JsonPath *      json_path_new           (void);
+
+gboolean        json_path_compile       (JsonPath    *path,
+                                         const char  *expression,
+                                         GError     **error);
+JsonNode *      json_path_match         (JsonPath    *path,
+                                         JsonNode    *root);
+
+JsonNode *      json_path_query         (const char  *expression,
+                                         JsonNode    *root,
+                                         GError     **error);
+
+G_END_DECLS
+
+#endif /* __JSON_PATH_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-reader.c b/src/glib-jsonrpc/json-glib/json-reader.c
new file mode 100644
index 0000000..89e422f
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-reader.c
@@ -0,0 +1,1069 @@
+/* json-reader.h - JSON cursor parser
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:json-reader
+ * @Title: JsonReader
+ * @short_description: A cursor-based parser
+ *
+ * #JsonReader provides a simple, cursor-based API for parsing a JSON DOM. It
+ * is similar, in spirit, to the XML Reader API.
+ *
+ * In case of error, #JsonReader will be set in an error state; all subsequent
+ * calls will simply be ignored until a function that resets the error state is
+ * called, e.g.:
+ *
+ * |[
+ * /&ast; ask for the 7th element; if the element does not exist, the
+ *  &ast; reader will be put in an error state
+ *  &ast;/
+ * json_reader_read_element (reader, 6);
+ *
+ * /&ast; in case of error, this will return NULL, otherwise it will
+ *  &ast; return the value of the element
+ *  &ast;/
+ * str = json_reader_get_string_value (value);
+ *
+ * /&ast; this function resets the error state if any was set &ast;/
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If you want to detect the error state as soon as possible, you can use
+ * json_reader_get_error():
+ *
+ * |[
+ * /&ast; like the example above, but in this case we print out the
+ *  &ast; error immediately
+ *  &ast;/
+ * if (!json_reader_read_element (reader, 6))
+ *   {
+ *     const GError *error = json_reader_get_error (reader);
+ *     g_print ("Unable to read the element: %s", error->message);
+ *   }
+ * ]|
+ *
+ * #JsonReader is available since JSON-GLib 0.12.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#if 0
+#include <glib/gi18n-lib.h>
+#else
+#define _(s) s
+#endif
+
+#include "json-reader.h"
+
+#include "json-types-private.h"
+
+#include "json-debug.h"
+
+#define json_reader_return_if_error_set(r)      G_STMT_START {  \
+        if (((JsonReader *) (r))->priv->error != NULL)          \
+          return;                               } G_STMT_END
+
+#define json_reader_return_val_if_error_set(r,v) G_STMT_START {  \
+        if (((JsonReader *) (r))->priv->error != NULL)           \
+          return (v);                           } G_STMT_END
+
+struct _JsonReaderPrivate
+{
+  JsonNode *root;
+
+  JsonNode *current_node;
+  JsonNode *previous_node;
+
+  gchar *current_member;
+
+  GError *error;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_ROOT,
+
+  PROP_LAST
+};
+
+static GParamSpec *reader_properties[PROP_LAST] = { NULL, };
+
+G_DEFINE_TYPE (JsonReader, json_reader, G_TYPE_OBJECT);
+
+static void
+json_reader_finalize (GObject *gobject)
+{
+  JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
+
+  if (priv->root != NULL)
+    json_node_free (priv->root);
+
+  if (priv->error != NULL)
+    g_clear_error (&priv->error);
+
+  g_free (priv->current_member);
+
+  G_OBJECT_CLASS (json_reader_parent_class)->finalize (gobject);
+}
+
+static void
+json_reader_set_property (GObject      *gobject,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_ROOT:
+      json_reader_set_root (JSON_READER (gobject), g_value_get_boxed (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+json_reader_get_property (GObject    *gobject,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_ROOT:
+      g_value_set_boxed (value, JSON_READER (gobject)->priv->root);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+json_reader_class_init (JsonReaderClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (JsonReaderPrivate));
+
+  /**
+   * JsonReader:root:
+   *
+   * The root of the JSON tree that the #JsonReader should read.
+   *
+   * Since: 0.12
+   */
+  reader_properties[PROP_ROOT] =
+    g_param_spec_boxed ("root",
+                        "Root Node",
+                        "The root of the tree to read",
+                        JSON_TYPE_NODE,
+                        G_PARAM_READWRITE |
+                        G_PARAM_CONSTRUCT |
+                        G_PARAM_STATIC_STRINGS);
+
+  gobject_class->finalize = json_reader_finalize;
+  gobject_class->set_property = json_reader_set_property;
+  gobject_class->get_property = json_reader_get_property;
+  g_object_class_install_properties (gobject_class, PROP_LAST, reader_properties);
+}
+
+static void
+json_reader_init (JsonReader *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, JSON_TYPE_READER,
+                                            JsonReaderPrivate);
+}
+
+GQuark
+json_reader_error_quark (void)
+{
+  return g_quark_from_static_string ("json-reader-error");
+}
+
+/**
+ * json_reader_new:
+ * @node: (allow-none): a #JsonNode, or %NULL
+ *
+ * Creates a new #JsonReader. You can use this object to read the contents of
+ * the JSON tree starting from @node
+ *
+ * Return value: the newly created #JsonReader. Use g_object_unref() to
+ *   release the allocated resources when done
+ *
+ * Since: 0.12
+ */
+JsonReader *
+json_reader_new (JsonNode *node)
+{
+  return g_object_new (JSON_TYPE_READER, "root", node, NULL);
+}
+
+/*
+ * json_reader_unset_error:
+ * @reader: a #JsonReader
+ *
+ * Unsets the error state of @reader, if set
+ */
+static inline void
+json_reader_unset_error (JsonReader *reader)
+{
+  if (reader->priv->error != NULL)
+    g_clear_error (&(reader->priv->error));
+}
+
+/**
+ * json_reader_set_root:
+ * @reader: a #JsonReader
+ * @root: (allow-none): a #JsonNode
+ *
+ * Sets the root #JsonNode to be read by @reader. The @reader will take
+ * a copy of @root
+ *
+ * If another #JsonNode is currently set as root, it will be replaced.
+ *
+ * Since: 0.12
+ */
+void
+json_reader_set_root (JsonReader *reader,
+                      JsonNode   *root)
+{
+  JsonReaderPrivate *priv;
+
+  g_return_if_fail (JSON_IS_READER (reader));
+
+  priv = reader->priv;
+
+  if (priv->root == root)
+    return;
+
+  if (priv->root != NULL)
+    {
+      json_node_free (priv->root);
+      priv->root = NULL;
+      priv->current_node = NULL;
+      priv->previous_node = NULL;
+    }
+
+  if (root != NULL)
+    {
+      priv->root = json_node_copy (root);
+      priv->current_node = priv->root;
+      priv->previous_node = NULL;
+    }
+
+  g_object_notify_by_pspec (G_OBJECT (reader), reader_properties[PROP_ROOT]);
+}
+
+/*
+ * json_reader_ser_error:
+ * @reader: a #JsonReader
+ * @error_code: the #JsonReaderError code for the error
+ * @error_fmt: format string
+ * @Varargs: list of arguments for the @error_fmt string
+ *
+ * Sets the error state of @reader using the given error code
+ * and string
+ *
+ * Return value: %FALSE, to be used to return immediately from
+ *   the caller function
+ */
+static gboolean
+json_reader_set_error (JsonReader      *reader,
+                       JsonReaderError  error_code,
+                       const gchar     *error_fmt,
+                       ...)
+{
+  JsonReaderPrivate *priv = reader->priv;
+  va_list args;
+  gchar *error_msg;
+
+  if (priv->error != NULL)
+    g_clear_error (&priv->error);
+
+  va_start (args, error_fmt);
+  error_msg = g_strdup_vprintf (error_fmt, args);
+  va_end (args);
+
+  g_set_error_literal (&priv->error, JSON_READER_ERROR,
+                       error_code,
+                       error_msg);
+
+  g_free (error_msg);
+
+  return FALSE;
+}
+
+/**
+ * json_reader_get_error:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the #GError currently set on @reader, if the #JsonReader
+ * is in error state
+ *
+ * Return value: (transfer none): the pointer to the error, or %NULL
+ *
+ * Since: 0.12
+ */
+const GError *
+json_reader_get_error (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+
+  return reader->priv->error;
+}
+
+/**
+ * json_reader_is_array:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on an array
+ *
+ * Return value: %TRUE if the #JsonReader is on an array, and %FALSE
+ *   otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_array (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  if (reader->priv->current_node == NULL)
+    return FALSE;
+
+  return JSON_NODE_HOLDS_ARRAY (reader->priv->current_node);
+}
+
+/**
+ * json_reader_is_object:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on an object
+ *
+ * Return value: %TRUE if the #JsonReader is on an object, and %FALSE
+ *   otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_object (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  if (reader->priv->current_node == NULL)
+    return FALSE;
+
+  return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node);
+}
+
+/**
+ * json_reader_is_value:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on a value
+ *
+ * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
+ *   otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_value (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  if (reader->priv->current_node == NULL)
+    return FALSE;
+
+  return JSON_NODE_HOLDS_VALUE (reader->priv->current_node);
+}
+
+/**
+ * json_reader_read_element:
+ * @reader: a #JsonReader
+ * @index_: the index of the element
+ *
+ * Advances the cursor of @reader to the element @index_ of the array
+ * or the object at the current position.
+ *
+ * You can use the json_reader_get_value* family of functions to retrieve
+ * the value of the element; for instance:
+ *
+ * |[
+ * json_reader_read_element (reader, 0);
+ * int_value = json_reader_get_int_value (reader);
+ * ]|
+ *
+ * After reading the value, json_reader_end_element() should be called to
+ * reposition the cursor inside the #JsonReader, e.g.:
+ *
+ * |[
+ * json_reader_read_element (reader, 1);
+ * str_value = json_reader_get_string_value (reader);
+ * json_reader_end_element (reader);
+ *
+ * json_reader_read_element (reader, 2);
+ * str_value = json_reader_get_string_value (reader);
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If @reader is not currently on an array or an object, or if the @index_ is
+ * bigger than the size of the array or the object, the #JsonReader will be
+ * put in an error state until json_reader_end_element() is called.
+ *
+ * Return value: %TRUE on success, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_read_element (JsonReader *reader,
+                          guint       index_)
+{
+  JsonReaderPrivate *priv;
+
+  g_return_val_if_fail (JSON_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  priv = reader->priv;
+
+  if (priv->current_node == NULL)
+    priv->current_node = priv->root;
+
+  if (!(JSON_NODE_HOLDS_ARRAY (priv->current_node) ||
+        JSON_NODE_HOLDS_OBJECT (priv->current_node)))
+    return json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
+                                  _("The current node is of type '%s', but "
+                                    "an array or an object was expected."),
+                                  json_node_type_name (priv->current_node));
+
+  switch (json_node_get_node_type (priv->current_node))
+    {
+    case JSON_NODE_ARRAY:
+      {
+        JsonArray *array = json_node_get_array (priv->current_node);
+
+        if (index_ >= json_array_get_length (array))
+          return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
+                                        _("The index '%d' is greater than the size "
+                                          "of the array at the current position."),
+                                        index_);
+
+        priv->previous_node = priv->current_node;
+        priv->current_node = json_array_get_element (array, index_);
+      }
+      break;
+
+    case JSON_NODE_OBJECT:
+      {
+        JsonObject *object = json_node_get_object (priv->current_node);
+        GList *members;
+        const gchar *name;
+
+        if (index_ >= json_object_get_size (object))
+          return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
+                                        _("The index '%d' is greater than the size "
+                                          "of the object at the current position."),
+                                        index_);
+
+        priv->previous_node = priv->current_node;
+        g_free (priv->current_member);
+
+        members = json_object_get_members (object);
+        name = g_list_nth_data (members, index_);
+
+        priv->current_node = json_object_get_member (object, name);
+        priv->current_member = g_strdup (name);
+
+        g_list_free (members);
+      }
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * json_reader_end_element:
+ * @reader: a #JsonReader
+ *
+ * Moves the cursor back to the previous node after being positioned
+ * inside an array
+ *
+ * This function resets the error state of @reader, if any was set
+ *
+ * Since: 0.12
+ */
+void
+json_reader_end_element (JsonReader *reader)
+{
+  JsonReaderPrivate *priv;
+  JsonNode *tmp;
+
+  g_return_if_fail (JSON_IS_READER (reader));
+
+  json_reader_unset_error (reader);
+
+  priv = reader->priv;
+
+  if (priv->previous_node != NULL)
+    tmp = json_node_get_parent (priv->previous_node);
+  else
+    tmp = NULL;
+
+  g_free (priv->current_member);
+  priv->current_member = NULL;
+
+  priv->current_node = priv->previous_node;
+  priv->previous_node = tmp;
+}
+
+/**
+ * json_reader_count_elements:
+ * @reader: a #JsonReader
+ *
+ * Counts the elements of the current position, if @reader is
+ * positioned on an array
+ *
+ * Return value: the number of elements, or -1. In case of failure
+ *   the #JsonReader is set in an error state
+ *
+ * Since: 0.12
+ */
+gint
+json_reader_count_elements (JsonReader *reader)
+{
+  JsonReaderPrivate *priv;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), -1);
+
+  priv = reader->priv;
+
+  if (priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return -1;
+    }
+
+  if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
+                             _("The current position holds a '%s' and not an array"),
+                             json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
+      return -1;
+    }
+
+  return json_array_get_length (json_node_get_array (priv->current_node));
+}
+
+/**
+ * json_reader_read_member:
+ * @reader: a #JsonReader
+ * @member_name: the name of the member to read
+ *
+ * Advances the cursor of @reader to the @member_name of the object at the
+ * current position.
+ *
+ * You can use the json_reader_get_value* family of functions to retrieve
+ * the value of the member; for instance:
+ *
+ * |[
+ * json_reader_read_member (reader, "width");
+ * width = json_reader_get_int_value (reader);
+ * ]|
+ *
+ * After reading the value, json_reader_end_member() should be called to
+ * reposition the cursor inside the #JsonReader, e.g.:
+ *
+ * |[
+ * json_reader_read_member (reader, "author");
+ * author = json_reader_get_string_value (reader);
+ * json_reader_end_element (reader);
+ *
+ * json_reader_read_element (reader, "title");
+ * title = json_reader_get_string_value (reader);
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If @reader is not currently on an object, or if the @member_name is not
+ * defined in the object, the #JsonReader will be put in an error state until
+ * json_reader_end_member() is called.
+ *
+ * Return value: %TRUE on success, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_read_member (JsonReader  *reader,
+                         const gchar *member_name)
+{
+  JsonReaderPrivate *priv;
+  JsonObject *object;
+
+  g_return_val_if_fail (JSON_READER (reader), FALSE);
+  g_return_val_if_fail (member_name != NULL, FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  priv = reader->priv;
+
+  if (priv->current_node == NULL)
+    priv->current_node = priv->root;
+
+  if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
+    return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
+                                  _("The current node is of type '%s', but "
+                                    "an object was expected."),
+                                  json_node_type_name (priv->current_node));
+
+  object = json_node_get_object (priv->current_node);
+  if (!json_object_has_member (object, member_name))
+    return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
+                                  _("The member '%s' is not defined in the "
+                                    "object at the current position."),
+                                  member_name);
+
+  g_free (priv->current_member);
+
+  priv->previous_node = priv->current_node;
+  priv->current_node = json_object_get_member (object, member_name);
+  priv->current_member = g_strdup (member_name);
+
+  return TRUE;
+}
+
+/**
+ * json_reader_end_member:
+ * @reader: a #JsonReader
+ *
+ * Moves the cursor back to the previous node after being positioned
+ * inside an object
+ *
+ * This function resets the error state of @reader, if any was set
+ *
+ * Since: 0.12
+ */
+void
+json_reader_end_member (JsonReader *reader)
+{
+  JsonReaderPrivate *priv;
+  JsonNode *tmp;
+
+  g_return_if_fail (JSON_IS_READER (reader));
+
+  json_reader_unset_error (reader);
+
+  priv = reader->priv;
+
+  if (priv->previous_node != NULL)
+    tmp = json_node_get_parent (priv->previous_node);
+  else
+    tmp = NULL;
+
+  g_free (priv->current_member);
+  priv->current_member = NULL;
+
+  priv->current_node = priv->previous_node;
+  priv->previous_node = tmp;
+}
+
+/**
+ * json_reader_list_members:
+ * @reader: a #JsonReader
+ *
+ * Retrieves a list of member names from the current position, if @reader
+ * is positioned on an object.
+ *
+ * Return value: (transfer full): a newly allocated, %NULL-terminated
+ *   array of strings holding the members name. Use g_strfreev() when
+ *   done.
+ *
+ * Since: 0.14
+ */
+gchar **
+json_reader_list_members (JsonReader *reader)
+{
+  JsonReaderPrivate *priv;
+  GList *members, *l;
+  gchar **retval;
+  gint i;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+
+  priv = reader->priv;
+
+  if (priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return NULL;
+    }
+
+  if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
+                             _("The current position holds a '%s' and not an object"),
+                             json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
+      return NULL;
+    }
+
+  members = json_object_get_members (json_node_get_object (priv->current_node));
+  if (members == NULL)
+    return NULL;
+
+  retval = g_new (gchar*, g_list_length (members) + 1);
+  for (l = members, i = 0; l != NULL; l = l->next, i += 1)
+    retval[i] = g_strdup (l->data);
+
+  retval[i] = NULL;
+
+  g_list_free (members);
+
+  return retval;
+}
+
+/**
+ * json_reader_count_members:
+ * @reader: a #JsonReader
+ *
+ * Counts the members of the current position, if @reader is
+ * positioned on an object
+ *
+ * Return value: the number of members, or -1. In case of failure
+ *   the #JsonReader is set in an error state
+ *
+ * Since: 0.12
+ */
+gint
+json_reader_count_members (JsonReader *reader)
+{
+  JsonReaderPrivate *priv;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), -1);
+
+  priv = reader->priv;
+
+  if (priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return -1;
+    }
+
+  if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
+                             _("The current position holds a '%s' and not an object"),
+                             json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
+      return -1;
+    }
+
+  return json_object_get_size (json_node_get_object (priv->current_node));
+}
+
+/**
+ * json_reader_get_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the #JsonNode of the current position of @reader
+ *
+ * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
+ *   is owned by the #JsonReader and it should not be modified or freed
+ *   directly
+ *
+ * Since: 0.12
+ */
+JsonNode *
+json_reader_get_value (JsonReader *reader)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+  json_reader_return_val_if_error_set (reader, NULL);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return NULL;
+    }
+
+  node = reader->priv->current_node;
+
+  if (!JSON_NODE_HOLDS_VALUE (node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
+                             _("The current position holds a '%s' and not a value"),
+                             json_node_type_get_name (JSON_NODE_TYPE (node)));
+      return NULL;
+    }
+
+  return reader->priv->current_node;
+}
+
+/**
+ * json_reader_get_int_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the integer value of the current position of @reader
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.12
+ */
+gint64
+json_reader_get_int_value (JsonReader *reader)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), 0);
+  json_reader_return_val_if_error_set (reader, 0);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return 0;
+    }
+
+  node = reader->priv->current_node;
+
+  if (!JSON_NODE_HOLDS_VALUE (node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
+                             _("The current position holds a '%s' and not a value"),
+                             json_node_type_get_name (JSON_NODE_TYPE (node)));
+      return 0;
+    }
+
+  if (json_node_get_value_type (node) != G_TYPE_INT64)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
+                             _("The current position does not hold an integer type"));
+      return 0;
+    }
+
+  return json_node_get_int (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_double_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the floating point value of the current position of @reader
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.12
+ */
+gdouble
+json_reader_get_double_value (JsonReader *reader)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
+  json_reader_return_val_if_error_set (reader, 0.0);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return 0.0;
+    }
+
+  node = reader->priv->current_node;
+
+  if (!JSON_NODE_HOLDS_VALUE (node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
+                             _("The current position holds a '%s' and not a value"),
+                             json_node_type_get_name (JSON_NODE_TYPE (node)));
+      return 0.0;
+    }
+
+  if (json_node_get_value_type (node) != G_TYPE_DOUBLE)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
+                             _("The current position does not hold a floating point type"));
+      return 0.0;
+    }
+
+  return json_node_get_double (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_string_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the string value of the current position of @reader
+ *
+ * Return value: the string value
+ *
+ * Since: 0.12
+ */
+const gchar *
+json_reader_get_string_value (JsonReader *reader)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+  json_reader_return_val_if_error_set (reader, NULL);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return NULL;
+    }
+
+  node = reader->priv->current_node;
+
+  if (!JSON_NODE_HOLDS_VALUE (node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
+                             _("The current position holds a '%s' and not a value"),
+                             json_node_type_get_name (JSON_NODE_TYPE (node)));
+      return NULL;
+    }
+
+  if (json_node_get_value_type (node) != G_TYPE_STRING)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
+                             _("The current position does not hold a string type"));
+      return NULL;
+    }
+
+  return json_node_get_string (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_boolean_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the boolean value of the current position of @reader
+ *
+ * Return value: the boolean value
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_get_boolean_value (JsonReader *reader)
+{
+  JsonNode *node;
+
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return FALSE;
+    }
+
+  node = reader->priv->current_node;
+
+  if (!JSON_NODE_HOLDS_VALUE (node))
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
+                             _("The current position holds a '%s' and not a value"),
+                             json_node_type_get_name (JSON_NODE_TYPE (node)));
+      return FALSE;
+    }
+
+  if (json_node_get_value_type (node) != G_TYPE_BOOLEAN)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
+                             _("The current position does not hold a boolean type"));
+      return FALSE;
+    }
+
+  return json_node_get_boolean (node);
+}
+
+/**
+ * json_reader_get_null_value:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the value of the current position of @reader is 'null'
+ *
+ * Return value: %TRUE if 'null' is set, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_get_null_value (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+  json_reader_return_val_if_error_set (reader, FALSE);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return FALSE;
+    }
+
+  return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_member_name:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the name of the current member.
+ *
+ * Return value: (transfer none): the name of the member, or %NULL
+ *
+ * Since: 0.14
+ */
+const gchar *
+json_reader_get_member_name (JsonReader *reader)
+{
+  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+  json_reader_return_val_if_error_set (reader, NULL);
+
+  if (reader->priv->current_node == NULL)
+    {
+      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
+                             _("No node available at the current position"));
+      return FALSE;
+    }
+
+  return reader->priv->current_member;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-reader.h b/src/glib-jsonrpc/json-glib/json-reader.h
new file mode 100644
index 0000000..6ee0b54
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-reader.h
@@ -0,0 +1,150 @@
+/* json-reader.h - JSON cursor parser
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_READER_H__
+#define __JSON_READER_H__
+
+#include <json-glib/json-types.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_READER                (json_reader_get_type ())
+#define JSON_READER(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_READER, JsonReader))
+#define JSON_IS_READER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_READER))
+#define JSON_READER_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), JSON_TYPE_READER, JsonReaderClass))
+#define JSON_IS_READER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), JSON_TYPE_READER))
+#define JSON_READER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), JSON_TYPE_READER, JsonReaderClass))
+
+/**
+ * JSON_READER_ERROR:
+ *
+ * Error domain for #JsonReader errors
+ *
+ * Since: 0.12
+ */
+#define JSON_READER_ERROR               (json_reader_error_quark ())
+
+typedef struct _JsonReader              JsonReader;
+typedef struct _JsonReaderPrivate       JsonReaderPrivate;
+typedef struct _JsonReaderClass         JsonReaderClass;
+
+/**
+ * JsonReaderError:
+ * @JSON_READER_ERROR_NO_ARRAY: No array found at the current position
+ * @JSON_READER_ERROR_INVALID_INDEX: Index out of bounds
+ * @JSON_READER_ERROR_NO_OBJECT: No object found at the current position
+ * @JSON_READER_ERROR_INVALID_MEMBER: Member not found
+ * @JSON_READER_ERROR_INVALID_NODE: No valid node found at the current position
+ * @JSON_READER_ERROR_NO_VALUE: The node at the current position does not
+ *   hold a value
+ * @JSON_READER_ERROR_INVALID_TYPE: The node at the current position does not
+ *   hold a value of the desired type
+ *
+ * Error codes enumeration for #JsonReader errors
+ *
+ * Since: 0.12
+ */
+typedef enum {
+  JSON_READER_ERROR_NO_ARRAY,
+  JSON_READER_ERROR_INVALID_INDEX,
+  JSON_READER_ERROR_NO_OBJECT,
+  JSON_READER_ERROR_INVALID_MEMBER,
+  JSON_READER_ERROR_INVALID_NODE,
+  JSON_READER_ERROR_NO_VALUE,
+  JSON_READER_ERROR_INVALID_TYPE
+} JsonReaderError;
+
+/**
+ * JsonReader:
+ *
+ * The <structname>JsonReader</structname> structure contains only
+ * private data and should only be accessed using the provided API
+ *
+ * Since: 0.12
+ */
+struct _JsonReader
+{
+  /*< private >*/
+  GObject parent_instance;
+
+  JsonReaderPrivate *priv;
+};
+
+/**
+ * JsonReaderClass:
+ *
+ * The <structname>JsonReaderClass</structname> structure contains only
+ * private data
+ *
+ * Since: 0.12
+ */
+struct _JsonReaderClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  void (*_json_padding0) (void);
+  void (*_json_padding1) (void);
+  void (*_json_padding2) (void);
+  void (*_json_padding3) (void);
+  void (*_json_padding4) (void);
+};
+
+GQuark json_reader_error_quark (void);
+GType json_reader_get_type (void) G_GNUC_CONST;
+
+JsonReader *           json_reader_new               (JsonNode     *node);
+
+void                   json_reader_set_root          (JsonReader   *reader,
+                                                      JsonNode     *root);
+
+const GError *         json_reader_get_error         (JsonReader   *reader);
+
+gboolean               json_reader_is_array          (JsonReader   *reader);
+gboolean               json_reader_read_element      (JsonReader   *reader,
+                                                      guint         index_);
+void                   json_reader_end_element       (JsonReader   *reader);
+gint                   json_reader_count_elements    (JsonReader   *reader);
+
+gboolean               json_reader_is_object         (JsonReader   *reader);
+gboolean               json_reader_read_member       (JsonReader   *reader,
+                                                      const gchar  *member_name);
+void                   json_reader_end_member        (JsonReader   *reader);
+gint                   json_reader_count_members     (JsonReader   *reader);
+gchar **               json_reader_list_members      (JsonReader   *reader);
+const gchar *          json_reader_get_member_name   (JsonReader   *reader);
+
+gboolean               json_reader_is_value          (JsonReader   *reader);
+JsonNode *             json_reader_get_value         (JsonReader   *reader);
+gint64                 json_reader_get_int_value     (JsonReader   *reader);
+gdouble                json_reader_get_double_value  (JsonReader   *reader);
+const gchar *          json_reader_get_string_value  (JsonReader   *reader);
+gboolean               json_reader_get_boolean_value (JsonReader   *reader);
+gboolean               json_reader_get_null_value    (JsonReader   *reader);
+
+G_END_DECLS
+
+#endif /* __JSON_READER_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-scanner.c b/src/glib-jsonrpc/json-glib/json-scanner.c
new file mode 100644
index 0000000..6eca2ba
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-scanner.c
@@ -0,0 +1,1861 @@
+/* json-scanner.c: Tokenizer for JSON
+ * Copyright (C) 2008 OpenedHand
+ *
+ * Based on JsonScanner: Flexible lexical scanner for general purpose.
+ * Copyright (C) 1997, 1998 Tim Janik
+ *
+ * Modified by Emmanuele Bassi <ebassi openedhand com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include "json-scanner.h"
+
+#ifdef G_OS_WIN32
+#include <io.h> /* For _read() */
+#endif
+
+struct _JsonScannerConfig
+{
+  /* Character sets
+   */
+  gchar *cset_skip_characters; /* default: " \t\n" */
+  gchar *cset_identifier_first;
+  gchar *cset_identifier_nth;
+  gchar *cpair_comment_single; /* default: "#\n" */
+  
+  /* Should symbol lookup work case sensitive? */
+  guint case_sensitive : 1;
+  
+  /* Boolean values to be adjusted "on the fly"
+   * to configure scanning behaviour.
+   */
+  guint skip_comment_multi : 1;  /* C like comment */
+  guint skip_comment_single : 1; /* single line comment */
+  guint scan_comment_multi : 1;  /* scan multi line comments? */
+  guint scan_identifier : 1;
+  guint scan_identifier_1char : 1;
+  guint scan_identifier_NULL : 1;
+  guint scan_symbols : 1;
+  guint scan_binary : 1;
+  guint scan_octal : 1;
+  guint scan_float : 1;
+  guint scan_hex : 1;            /* `0x0ff0' */
+  guint scan_hex_dollar : 1;     /* `$0ff0' */
+  guint scan_string_sq : 1;      /* string: 'anything' */
+  guint scan_string_dq : 1;      /* string: "\\-escapes!\n" */
+  guint numbers_2_int : 1;       /* bin, octal, hex => int */
+  guint int_2_float : 1;         /* int => G_TOKEN_FLOAT? */
+  guint identifier_2_string : 1;
+  guint char_2_token : 1;        /* return G_TOKEN_CHAR? */
+  guint symbol_2_token : 1;
+  guint scope_0_fallback : 1;    /* try scope 0 on lookups? */
+  guint store_int64 : 1;         /* use value.v_int64 rather than v_int */
+  guint padding_dummy;
+};
+
+static JsonScannerConfig json_scanner_config_template =
+{
+  ( " \t\r\n" )		/* cset_skip_characters */,
+  (
+   "_"
+   G_CSET_a_2_z
+   G_CSET_A_2_Z
+  )			/* cset_identifier_first */,
+  (
+   G_CSET_DIGITS
+   "-_"
+   G_CSET_a_2_z
+   G_CSET_A_2_Z
+  )			/* cset_identifier_nth */,
+  ( "//\n" )		/* cpair_comment_single */,
+  TRUE			/* case_sensitive */,
+  TRUE			/* skip_comment_multi */,
+  TRUE			/* skip_comment_single */,
+  FALSE			/* scan_comment_multi */,
+  TRUE			/* scan_identifier */,
+  TRUE			/* scan_identifier_1char */,
+  FALSE			/* scan_identifier_NULL */,
+  TRUE			/* scan_symbols */,
+  TRUE			/* scan_binary */,
+  TRUE			/* scan_octal */,
+  TRUE			/* scan_float */,
+  TRUE			/* scan_hex */,
+  TRUE			/* scan_hex_dollar */,
+  TRUE			/* scan_string_sq */,
+  TRUE			/* scan_string_dq */,
+  TRUE			/* numbers_2_int */,
+  FALSE			/* int_2_float */,
+  FALSE			/* identifier_2_string */,
+  TRUE			/* char_2_token */,
+  TRUE			/* symbol_2_token */,
+  FALSE			/* scope_0_fallback */,
+  TRUE                  /* store_int64 */
+};
+
+/* --- defines --- */
+#define	to_lower(c)				( \
+	(guchar) (							\
+	  ( (((guchar)(c))>='A' && ((guchar)(c))<='Z') * ('a'-'A') ) |	\
+	  ( (((guchar)(c))>=192 && ((guchar)(c))<=214) * (224-192) ) |	\
+	  ( (((guchar)(c))>=216 && ((guchar)(c))<=222) * (248-216) ) |	\
+	  ((guchar)(c))							\
+	)								\
+)
+
+#define	READ_BUFFER_SIZE	(4000)
+
+static const gchar json_symbol_names[] =
+  "true\0"
+  "false\0"
+  "null\0"
+  "var\0";
+
+static const struct
+{
+  guint name_offset;
+  guint token;
+} json_symbols[] = {
+  {  0, JSON_TOKEN_TRUE },
+  {  5, JSON_TOKEN_FALSE },
+  { 11, JSON_TOKEN_NULL },
+  { 16, JSON_TOKEN_VAR }
+};
+
+static const guint n_json_symbols = G_N_ELEMENTS (json_symbols);
+
+/* --- typedefs --- */
+typedef	struct	_JsonScannerKey JsonScannerKey;
+
+struct	_JsonScannerKey
+{
+  guint scope_id;
+  gchar *symbol;
+  gpointer value;
+};
+
+/* --- prototypes --- */
+static gboolean	json_scanner_key_equal (gconstpointer v1,
+                                        gconstpointer v2);
+static guint    json_scanner_key_hash  (gconstpointer v);
+
+static inline
+JsonScannerKey *json_scanner_lookup_internal (JsonScanner *scanner,
+                                              guint        scope_id,
+                                              const gchar *symbol);
+static void     json_scanner_get_token_ll    (JsonScanner *scanner,
+                                              GTokenType  *token_p,
+                                              GTokenValue *value_p,
+                                              guint       *line_p,
+                                              guint       *position_p);
+static void	json_scanner_get_token_i     (JsonScanner *scanner,
+                                              GTokenType  *token_p,
+                                              GTokenValue *value_p,
+                                              guint       *line_p,
+                                              guint       *position_p);
+
+static guchar   json_scanner_peek_next_char  (JsonScanner *scanner);
+static guchar   json_scanner_get_char        (JsonScanner *scanner,
+                                              guint       *line_p,
+                                              guint       *position_p);
+static gunichar json_scanner_get_unichar     (JsonScanner *scanner,
+                                              guint       *line_p,
+                                              guint       *position_p);
+static void     json_scanner_msg_handler     (JsonScanner *scanner,
+                                              gchar       *message,
+                                              gboolean     is_error);
+
+/* --- functions --- */
+static inline gint
+json_scanner_char_2_num (guchar c,
+                         guchar base)
+{
+  if (c >= '0' && c <= '9')
+    c -= '0';
+  else if (c >= 'A' && c <= 'Z')
+    c -= 'A' - 10;
+  else if (c >= 'a' && c <= 'z')
+    c -= 'a' - 10;
+  else
+    return -1;
+  
+  if (c < base)
+    return c;
+  
+  return -1;
+}
+
+JsonScanner *
+json_scanner_new (void)
+{
+  JsonScanner *scanner;
+  JsonScannerConfig *config_templ;
+  
+  config_templ = &json_scanner_config_template;
+  
+  scanner = g_new0 (JsonScanner, 1);
+  
+  scanner->user_data = NULL;
+  scanner->max_parse_errors = 1;
+  scanner->parse_errors	= 0;
+  scanner->input_name = NULL;
+  g_datalist_init (&scanner->qdata);
+  
+  scanner->config = g_new0 (JsonScannerConfig, 1);
+  
+  scanner->config->case_sensitive	 = config_templ->case_sensitive;
+  scanner->config->cset_skip_characters	 = config_templ->cset_skip_characters;
+  if (!scanner->config->cset_skip_characters)
+    scanner->config->cset_skip_characters = "";
+  scanner->config->cset_identifier_first = config_templ->cset_identifier_first;
+  scanner->config->cset_identifier_nth	 = config_templ->cset_identifier_nth;
+  scanner->config->cpair_comment_single	 = config_templ->cpair_comment_single;
+  scanner->config->skip_comment_multi	 = config_templ->skip_comment_multi;
+  scanner->config->skip_comment_single	 = config_templ->skip_comment_single;
+  scanner->config->scan_comment_multi	 = config_templ->scan_comment_multi;
+  scanner->config->scan_identifier	 = config_templ->scan_identifier;
+  scanner->config->scan_identifier_1char = config_templ->scan_identifier_1char;
+  scanner->config->scan_identifier_NULL	 = config_templ->scan_identifier_NULL;
+  scanner->config->scan_symbols		 = config_templ->scan_symbols;
+  scanner->config->scan_binary		 = config_templ->scan_binary;
+  scanner->config->scan_octal		 = config_templ->scan_octal;
+  scanner->config->scan_float		 = config_templ->scan_float;
+  scanner->config->scan_hex		 = config_templ->scan_hex;
+  scanner->config->scan_hex_dollar	 = config_templ->scan_hex_dollar;
+  scanner->config->scan_string_sq	 = config_templ->scan_string_sq;
+  scanner->config->scan_string_dq	 = config_templ->scan_string_dq;
+  scanner->config->numbers_2_int	 = config_templ->numbers_2_int;
+  scanner->config->int_2_float		 = config_templ->int_2_float;
+  scanner->config->identifier_2_string	 = config_templ->identifier_2_string;
+  scanner->config->char_2_token		 = config_templ->char_2_token;
+  scanner->config->symbol_2_token	 = config_templ->symbol_2_token;
+  scanner->config->scope_0_fallback	 = config_templ->scope_0_fallback;
+  scanner->config->store_int64		 = config_templ->store_int64;
+  
+  scanner->token = G_TOKEN_NONE;
+  scanner->value.v_int64 = 0;
+  scanner->line = 1;
+  scanner->position = 0;
+  
+  scanner->next_token = G_TOKEN_NONE;
+  scanner->next_value.v_int64 = 0;
+  scanner->next_line = 1;
+  scanner->next_position = 0;
+  
+  scanner->symbol_table = g_hash_table_new (json_scanner_key_hash,
+                                            json_scanner_key_equal);
+  scanner->input_fd = -1;
+  scanner->text = NULL;
+  scanner->text_end = NULL;
+  scanner->buffer = NULL;
+  scanner->scope_id = 0;
+  
+  scanner->msg_handler = json_scanner_msg_handler;
+  
+  return scanner;
+}
+
+static inline void
+json_scanner_free_value (GTokenType  *token_p,
+                         GTokenValue *value_p)
+{
+  switch (*token_p)
+    {
+    case G_TOKEN_STRING:
+    case G_TOKEN_IDENTIFIER:
+    case G_TOKEN_IDENTIFIER_NULL:
+    case G_TOKEN_COMMENT_SINGLE:
+    case G_TOKEN_COMMENT_MULTI:
+      g_free (value_p->v_string);
+      break;
+      
+    default:
+      break;
+    }
+  
+  *token_p = G_TOKEN_NONE;
+}
+
+static void
+json_scanner_destroy_symbol_table_entry (gpointer _key,
+                                         gpointer _value,
+                                         gpointer _data)
+{
+  JsonScannerKey *key = _key;
+  
+  g_free (key->symbol);
+  g_slice_free (JsonScannerKey, key);
+}
+
+void
+json_scanner_destroy (JsonScanner *scanner)
+{
+  g_return_if_fail (scanner != NULL);
+  
+  g_datalist_clear (&scanner->qdata);
+  g_hash_table_foreach (scanner->symbol_table, 
+			json_scanner_destroy_symbol_table_entry,
+                        NULL);
+  g_hash_table_destroy (scanner->symbol_table);
+  json_scanner_free_value (&scanner->token, &scanner->value);
+  json_scanner_free_value (&scanner->next_token, &scanner->next_value);
+  g_free (scanner->config);
+  g_free (scanner->buffer);
+  g_free (scanner);
+}
+
+static void
+json_scanner_msg_handler (JsonScanner *scanner,
+                          gchar       *message,
+                          gboolean     is_error)
+{
+  g_return_if_fail (scanner != NULL);
+  
+  g_fprintf (stderr, "%s:%d: ",
+	     scanner->input_name ? scanner->input_name : "<memory>",
+	     scanner->line);
+  if (is_error)
+    g_fprintf (stderr, "error: ");
+
+  g_fprintf (stderr, "%s\n", message);
+}
+
+void
+json_scanner_error (JsonScanner *scanner,
+                    const gchar *format,
+                    ...)
+{
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (format != NULL);
+  
+  scanner->parse_errors++;
+  
+  if (scanner->msg_handler)
+    {
+      va_list args;
+      gchar *string;
+      
+      va_start (args, format);
+      string = g_strdup_vprintf (format, args);
+      va_end (args);
+      
+      scanner->msg_handler (scanner, string, TRUE);
+      
+      g_free (string);
+    }
+}
+
+void
+json_scanner_warn (JsonScanner *scanner,
+                   const gchar *format,
+                   ...)
+{
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (format != NULL);
+  
+  if (scanner->msg_handler)
+    {
+      va_list args;
+      gchar *string;
+      
+      va_start (args, format);
+      string = g_strdup_vprintf (format, args);
+      va_end (args);
+      
+      scanner->msg_handler (scanner, string, FALSE);
+      
+      g_free (string);
+    }
+}
+
+static gboolean
+json_scanner_key_equal (gconstpointer v1,
+                        gconstpointer v2)
+{
+  const JsonScannerKey *key1 = v1;
+  const JsonScannerKey *key2 = v2;
+  
+  return (key1->scope_id == key2->scope_id) &&
+         (strcmp (key1->symbol, key2->symbol) == 0);
+}
+
+static guint
+json_scanner_key_hash (gconstpointer v)
+{
+  const JsonScannerKey *key = v;
+  gchar *c;
+  guint h;
+  
+  h = key->scope_id;
+  for (c = key->symbol; *c; c++)
+    h = (h << 5) - h + *c;
+  
+  return h;
+}
+
+static inline JsonScannerKey *
+json_scanner_lookup_internal (JsonScanner *scanner,
+                              guint        scope_id,
+                              const gchar *symbol)
+{
+  JsonScannerKey *key_p;
+  JsonScannerKey key;
+  
+  key.scope_id = scope_id;
+  
+  if (!scanner->config->case_sensitive)
+    {
+      gchar *d;
+      const gchar *c;
+      
+      key.symbol = g_new (gchar, strlen (symbol) + 1);
+      for (d = key.symbol, c = symbol; *c; c++, d++)
+	*d = to_lower (*c);
+      *d = 0;
+      key_p = g_hash_table_lookup (scanner->symbol_table, &key);
+      g_free (key.symbol);
+    }
+  else
+    {
+      key.symbol = (gchar*) symbol;
+      key_p = g_hash_table_lookup (scanner->symbol_table, &key);
+    }
+  
+  return key_p;
+}
+
+void
+json_scanner_scope_add_symbol (JsonScanner *scanner,
+                               guint        scope_id,
+                               const gchar *symbol,
+                               gpointer     value)
+{
+  JsonScannerKey *key;
+
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (symbol != NULL);
+
+  key = json_scanner_lookup_internal (scanner, scope_id, symbol);
+  if (!key)
+    {
+      key = g_slice_new (JsonScannerKey);
+      key->scope_id = scope_id;
+      key->symbol = g_strdup (symbol);
+      key->value = value;
+      if (!scanner->config->case_sensitive)
+	{
+	  gchar *c;
+
+	  c = key->symbol;
+	  while (*c != 0)
+	    {
+	      *c = to_lower (*c);
+	      c++;
+	    }
+	}
+
+      g_hash_table_insert (scanner->symbol_table, key, key);
+    }
+  else
+    key->value = value;
+}
+
+void
+json_scanner_scope_remove_symbol (JsonScanner *scanner,
+                                  guint        scope_id,
+                                  const gchar *symbol)
+{
+  JsonScannerKey *key;
+
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (symbol != NULL);
+
+  key = json_scanner_lookup_internal (scanner, scope_id, symbol);
+  if (key)
+    {
+      g_hash_table_remove (scanner->symbol_table, key);
+      g_free (key->symbol);
+      g_slice_free (JsonScannerKey, key);
+    }
+}
+
+gpointer
+json_scanner_lookup_symbol (JsonScanner *scanner,
+                            const gchar *symbol)
+{
+  JsonScannerKey *key;
+  guint scope_id;
+
+  g_return_val_if_fail (scanner != NULL, NULL);
+
+  if (!symbol)
+    return NULL;
+
+  scope_id = scanner->scope_id;
+  key = json_scanner_lookup_internal (scanner, scope_id, symbol);
+  if (!key && scope_id && scanner->config->scope_0_fallback)
+    key = json_scanner_lookup_internal (scanner, 0, symbol);
+
+  if (key)
+    return key->value;
+  else
+    return NULL;
+}
+
+gpointer
+json_scanner_scope_lookup_symbol (JsonScanner *scanner,
+                                  guint        scope_id,
+                                  const gchar *symbol)
+{
+  JsonScannerKey *key;
+
+  g_return_val_if_fail (scanner != NULL, NULL);
+
+  if (!symbol)
+    return NULL;
+
+  key = json_scanner_lookup_internal (scanner, scope_id, symbol);
+
+  if (key)
+    return key->value;
+  else
+    return NULL;
+}
+
+guint
+json_scanner_set_scope (JsonScanner *scanner,
+                        guint        scope_id)
+{
+  guint old_scope_id;
+
+  g_return_val_if_fail (scanner != NULL, 0);
+
+  old_scope_id = scanner->scope_id;
+  scanner->scope_id = scope_id;
+
+  return old_scope_id;
+}
+
+typedef struct {
+  GHFunc func;
+  gpointer data;
+  guint scope_id;
+} ForeachClosure;
+
+static void
+json_scanner_foreach_internal (gpointer _key,
+                               gpointer _value,
+                               gpointer _user_data)
+{
+  JsonScannerKey *key = _value;
+  ForeachClosure *closure = _user_data;
+
+  if (key->scope_id == closure->scope_id)
+    closure->func (key->symbol, key->value, closure->data);
+}
+
+void
+json_scanner_scope_foreach_symbol (JsonScanner *scanner,
+                                   guint        scope_id,
+                                   GHFunc       func,
+                                   gpointer     user_data)
+{
+  ForeachClosure closure;
+
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (func != NULL);
+
+  closure.func = func;
+  closure.data = user_data;
+  closure.scope_id = scope_id;
+
+  g_hash_table_foreach (scanner->symbol_table,
+                        json_scanner_foreach_internal,
+                        &closure);
+}
+
+GTokenType
+json_scanner_peek_next_token (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+  if (scanner->next_token == G_TOKEN_NONE)
+    {
+      scanner->next_line = scanner->line;
+      scanner->next_position = scanner->position;
+      json_scanner_get_token_i (scanner,
+                                &scanner->next_token,
+                                &scanner->next_value,
+                                &scanner->next_line,
+                                &scanner->next_position);
+    }
+
+  return scanner->next_token;
+}
+
+GTokenType
+json_scanner_get_next_token (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+  if (scanner->next_token != G_TOKEN_NONE)
+    {
+      json_scanner_free_value (&scanner->token, &scanner->value);
+
+      scanner->token = scanner->next_token;
+      scanner->value = scanner->next_value;
+      scanner->line = scanner->next_line;
+      scanner->position = scanner->next_position;
+      scanner->next_token = G_TOKEN_NONE;
+    }
+  else
+    json_scanner_get_token_i (scanner,
+                              &scanner->token,
+                              &scanner->value,
+                              &scanner->line,
+                              &scanner->position);
+
+  return scanner->token;
+}
+
+GTokenType
+json_scanner_cur_token (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+  return scanner->token;
+}
+
+GTokenValue
+json_scanner_cur_value (JsonScanner *scanner)
+{
+  GTokenValue v;
+
+  v.v_int64 = 0;
+
+  g_return_val_if_fail (scanner != NULL, v);
+
+  /* MSC isn't capable of handling return scanner->value; ? */
+
+  v = scanner->value;
+
+  return v;
+}
+
+guint
+json_scanner_cur_line (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, 0);
+
+  return scanner->line;
+}
+
+guint
+json_scanner_cur_position (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, 0);
+
+  return scanner->position;
+}
+
+gboolean
+json_scanner_eof (JsonScanner *scanner)
+{
+  g_return_val_if_fail (scanner != NULL, TRUE);
+
+  return scanner->token == G_TOKEN_EOF || scanner->token == G_TOKEN_ERROR;
+}
+
+void
+json_scanner_input_file (JsonScanner *scanner,
+                         gint         input_fd)
+{
+  g_return_if_fail (scanner != NULL);
+  g_return_if_fail (input_fd >= 0);
+
+  if (scanner->input_fd >= 0)
+    json_scanner_sync_file_offset (scanner);
+
+  scanner->token = G_TOKEN_NONE;
+  scanner->value.v_int64 = 0;
+  scanner->line = 1;
+  scanner->position = 0;
+  scanner->next_token = G_TOKEN_NONE;
+
+  scanner->input_fd = input_fd;
+  scanner->text = NULL;
+  scanner->text_end = NULL;
+
+  if (!scanner->buffer)
+    scanner->buffer = g_new (gchar, READ_BUFFER_SIZE + 1);
+}
+
+void
+json_scanner_input_text (JsonScanner *scanner,
+                         const gchar *text,
+                         guint        text_len)
+{
+  g_return_if_fail (scanner != NULL);
+  if (text_len)
+    g_return_if_fail (text != NULL);
+  else
+    text = NULL;
+
+  if (scanner->input_fd >= 0)
+    json_scanner_sync_file_offset (scanner);
+
+  scanner->token = G_TOKEN_NONE;
+  scanner->value.v_int64 = 0;
+  scanner->line = 1;
+  scanner->position = 0;
+  scanner->next_token = G_TOKEN_NONE;
+
+  scanner->input_fd = -1;
+  scanner->text = text;
+  scanner->text_end = text + text_len;
+
+  if (scanner->buffer)
+    {
+      g_free (scanner->buffer);
+      scanner->buffer = NULL;
+    }
+}
+
+static guchar
+json_scanner_peek_next_char (JsonScanner *scanner)
+{
+  if (scanner->text < scanner->text_end)
+    return *scanner->text;
+  else if (scanner->input_fd >= 0)
+    {
+      gint count;
+      gchar *buffer;
+
+      buffer = scanner->buffer;
+      do
+	{
+	  count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
+	}
+      while (count == -1 && (errno == EINTR || errno == EAGAIN));
+
+      if (count < 1)
+	{
+	  scanner->input_fd = -1;
+
+	  return 0;
+	}
+      else
+	{
+	  scanner->text = buffer;
+	  scanner->text_end = buffer + count;
+
+	  return *buffer;
+	}
+    }
+  else
+    return 0;
+}
+
+void
+json_scanner_sync_file_offset (JsonScanner *scanner)
+{
+  g_return_if_fail (scanner != NULL);
+
+  /* for file input, rewind the filedescriptor to the current
+   * buffer position and blow the file read ahead buffer. useful
+   * for third party uses of our file descriptor, which hooks 
+   * onto the current scanning position.
+   */
+
+  if (scanner->input_fd >= 0 && scanner->text_end > scanner->text)
+    {
+      gint buffered;
+
+      buffered = scanner->text_end - scanner->text;
+      if (lseek (scanner->input_fd, - buffered, SEEK_CUR) >= 0)
+	{
+	  /* we succeeded, blow our buffer's contents now */
+	  scanner->text = NULL;
+	  scanner->text_end = NULL;
+	}
+      else
+	errno = 0;
+    }
+}
+
+static guchar
+json_scanner_get_char (JsonScanner *scanner,
+                       guint       *line_p,
+                       guint       *position_p)
+{
+  guchar fchar;
+
+  if (scanner->text < scanner->text_end)
+    fchar = *(scanner->text++);
+  else if (scanner->input_fd >= 0)
+    {
+      gint count;
+      gchar *buffer;
+
+      buffer = scanner->buffer;
+      do
+	{
+	  count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
+	}
+      while (count == -1 && (errno == EINTR || errno == EAGAIN));
+
+      if (count < 1)
+	{
+	  scanner->input_fd = -1;
+	  fchar = 0;
+	}
+      else
+	{
+	  scanner->text = buffer + 1;
+	  scanner->text_end = buffer + count;
+	  fchar = *buffer;
+	  if (!fchar)
+	    {
+	      json_scanner_sync_file_offset (scanner);
+	      scanner->text_end = scanner->text;
+	      scanner->input_fd = -1;
+	    }
+	}
+    }
+  else
+    fchar = 0;
+  
+  if (fchar == '\n')
+    {
+      (*position_p) = 0;
+      (*line_p)++;
+    }
+  else if (fchar)
+    {
+      (*position_p)++;
+    }
+  
+  return fchar;
+}
+
+#define is_hex_digit(c)         (((c) >= '0' && (c) <= '9') || \
+                                 ((c) >= 'a' && (c) <= 'f') || \
+                                 ((c) >= 'A' && (c) <= 'F'))
+#define to_hex_digit(c)         (((c) <= '9') ? (c) - '0' : ((c) & 7) + 9)
+
+static gunichar
+json_scanner_get_unichar (JsonScanner *scanner,
+                          guint       *line_p,
+                          guint       *position_p)
+{
+  gunichar uchar;
+  gchar ch;
+  gint i;
+
+  uchar = 0;
+  for (i = 0; i < 4; i++)
+    {
+      ch = json_scanner_get_char (scanner, line_p, position_p);
+
+      if (is_hex_digit (ch))
+        uchar += ((gunichar) to_hex_digit (ch) << ((3 - i) * 4));
+      else
+        break;
+    }
+
+  g_assert (g_unichar_validate (uchar) || g_unichar_type (uchar) == G_UNICODE_SURROGATE);
+
+  return uchar;
+}
+
+void
+json_scanner_unexp_token (JsonScanner *scanner,
+                          GTokenType   expected_token,
+                          const gchar *identifier_spec,
+                          const gchar *symbol_spec,
+                          const gchar *symbol_name,
+                          const gchar *message,
+                          gint         is_error)
+{
+  gchar	*token_string;
+  guint	token_string_len;
+  gchar	*expected_string;
+  guint	expected_string_len;
+  gchar	*message_prefix;
+  gboolean print_unexp;
+  void (*msg_handler) (JsonScanner*, const gchar*, ...);
+  
+  g_return_if_fail (scanner != NULL);
+  
+  if (is_error)
+    msg_handler = json_scanner_error;
+  else
+    msg_handler = json_scanner_warn;
+  
+  if (!identifier_spec)
+    identifier_spec = "identifier";
+  if (!symbol_spec)
+    symbol_spec = "symbol";
+  
+  token_string_len = 56;
+  token_string = g_new (gchar, token_string_len + 1);
+  expected_string_len = 64;
+  expected_string = g_new (gchar, expected_string_len + 1);
+  print_unexp = TRUE;
+  
+  switch (scanner->token)
+    {
+    case G_TOKEN_EOF:
+      g_snprintf (token_string, token_string_len, "end of file");
+      break;
+      
+    default:
+      if (scanner->token >= 1 && scanner->token <= 255)
+	{
+	  if ((scanner->token >= ' ' && scanner->token <= '~') ||
+	      strchr (scanner->config->cset_identifier_first, scanner->token) ||
+	      strchr (scanner->config->cset_identifier_nth, scanner->token))
+	    g_snprintf (token_string, token_string_len, "character `%c'", scanner->token);
+	  else
+	    g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token);
+	  break;
+	}
+      else if (!scanner->config->symbol_2_token)
+	{
+	  g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
+	  break;
+	}
+      /* fall through */
+    case G_TOKEN_SYMBOL:
+      if (expected_token == G_TOKEN_SYMBOL ||
+	  (scanner->config->symbol_2_token &&
+	   expected_token > G_TOKEN_LAST))
+	print_unexp = FALSE;
+      if (symbol_name)
+	g_snprintf (token_string, token_string_len,
+                    "%s%s `%s'",
+                    print_unexp ? "" : "invalid ",
+                    symbol_spec,
+                    symbol_name);
+      else
+	g_snprintf (token_string, token_string_len,
+                    "%s%s",
+                    print_unexp ? "" : "invalid ",
+                    symbol_spec);
+      break;
+ 
+    case G_TOKEN_ERROR:
+      print_unexp = FALSE;
+      expected_token = G_TOKEN_NONE;
+      switch (scanner->value.v_error)
+	{
+	case G_ERR_UNEXP_EOF:
+	  g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
+	  break;
+	  
+	case G_ERR_UNEXP_EOF_IN_STRING:
+	  g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
+	  break;
+	  
+	case G_ERR_UNEXP_EOF_IN_COMMENT:
+	  g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
+	  break;
+	  
+	case G_ERR_NON_DIGIT_IN_CONST:
+	  g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
+	  break;
+	  
+	case G_ERR_FLOAT_RADIX:
+	  g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
+	  break;
+	  
+	case G_ERR_FLOAT_MALFORMED:
+	  g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
+	  break;
+	  
+	case G_ERR_DIGIT_RADIX:
+	  g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
+	  break;
+	  
+	case G_ERR_UNKNOWN:
+	default:
+	  g_snprintf (token_string, token_string_len, "scanner: unknown error");
+	  break;
+	}
+      break;
+      
+    case G_TOKEN_CHAR:
+      g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
+      break;
+      
+    case G_TOKEN_IDENTIFIER:
+    case G_TOKEN_IDENTIFIER_NULL:
+      if (expected_token == G_TOKEN_IDENTIFIER ||
+	  expected_token == G_TOKEN_IDENTIFIER_NULL)
+	print_unexp = FALSE;
+      g_snprintf (token_string, token_string_len,
+                  "%s%s `%s'",
+                  print_unexp ? "" : "invalid ",
+                  identifier_spec,
+                  scanner->token == G_TOKEN_IDENTIFIER ? scanner->value.v_string : "null");
+      break;
+      
+    case G_TOKEN_BINARY:
+    case G_TOKEN_OCTAL:
+    case G_TOKEN_INT:
+    case G_TOKEN_HEX:
+      if (scanner->config->store_int64)
+	g_snprintf (token_string, token_string_len, "number `%" G_GUINT64_FORMAT "'", scanner->value.v_int64);
+      else
+	g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
+      break;
+      
+    case G_TOKEN_FLOAT:
+      g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
+      break;
+      
+    case G_TOKEN_STRING:
+      if (expected_token == G_TOKEN_STRING)
+	print_unexp = FALSE;
+      g_snprintf (token_string, token_string_len,
+                  "%s%sstring constant \"%s\"",
+                  print_unexp ? "" : "invalid ",
+                  scanner->value.v_string[0] == 0 ? "empty " : "",
+                  scanner->value.v_string);
+      token_string[token_string_len - 2] = '"';
+      token_string[token_string_len - 1] = 0;
+      break;
+      
+    case G_TOKEN_COMMENT_SINGLE:
+    case G_TOKEN_COMMENT_MULTI:
+      g_snprintf (token_string, token_string_len, "comment");
+      break;
+      
+    case G_TOKEN_NONE:
+      /* somehow the user's parsing code is screwed, there isn't much
+       * we can do about it.
+       * Note, a common case to trigger this is
+       * json_scanner_peek_next_token(); json_scanner_unexp_token();
+       * without an intermediate json_scanner_get_next_token().
+       */
+      g_assert_not_reached ();
+      break;
+    }
+  
+  
+  switch (expected_token)
+    {
+      gboolean need_valid;
+      gchar *tstring;
+    case G_TOKEN_EOF:
+      g_snprintf (expected_string, expected_string_len, "end of file");
+      break;
+    default:
+      if (expected_token >= 1 && expected_token <= 255)
+	{
+	  if ((expected_token >= ' ' && expected_token <= '~') ||
+	      strchr (scanner->config->cset_identifier_first, expected_token) ||
+	      strchr (scanner->config->cset_identifier_nth, expected_token))
+	    g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
+	  else
+	    g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
+	  break;
+	}
+      else if (!scanner->config->symbol_2_token)
+	{
+	  g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
+	  break;
+	}
+      /* fall through */
+    case G_TOKEN_SYMBOL:
+      need_valid = (scanner->token == G_TOKEN_SYMBOL ||
+		    (scanner->config->symbol_2_token &&
+		     scanner->token > G_TOKEN_LAST));
+      g_snprintf (expected_string, expected_string_len,
+                  "%s%s",
+                  need_valid ? "valid " : "",
+                  symbol_spec);
+      /* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */
+      break;
+    case G_TOKEN_CHAR:
+      g_snprintf (expected_string, expected_string_len, "%scharacter",
+		  scanner->token == G_TOKEN_CHAR ? "valid " : "");
+      break;
+    case G_TOKEN_BINARY:
+      tstring = "binary";
+      g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_OCTAL:
+      tstring = "octal";
+      g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_INT:
+      tstring = "integer";
+      g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_HEX:
+      tstring = "hexadecimal";
+      g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_FLOAT:
+      tstring = "float";
+      g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_STRING:
+      g_snprintf (expected_string,
+		  expected_string_len,
+		  "%sstring constant",
+		  scanner->token == G_TOKEN_STRING ? "valid " : "");
+      break;
+    case G_TOKEN_IDENTIFIER:
+    case G_TOKEN_IDENTIFIER_NULL:
+      need_valid = (scanner->token == G_TOKEN_IDENTIFIER_NULL ||
+		    scanner->token == G_TOKEN_IDENTIFIER);
+      g_snprintf (expected_string,
+		  expected_string_len,
+		  "%s%s",
+		  need_valid ? "valid " : "",
+		  identifier_spec);
+      break;
+    case G_TOKEN_COMMENT_SINGLE:
+      tstring = "single-line";
+      g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_COMMENT_MULTI:
+      tstring = "multi-line";
+      g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
+		  scanner->token == expected_token ? "valid " : "", tstring);
+      break;
+    case G_TOKEN_NONE:
+    case G_TOKEN_ERROR:
+      /* this is handled upon printout */
+      break;
+    }
+  
+  if (message && message[0] != 0)
+    message_prefix = " - ";
+  else
+    {
+      message_prefix = "";
+      message = "";
+    }
+  if (expected_token == G_TOKEN_ERROR)
+    {
+      msg_handler (scanner,
+		   "failure around %s%s%s",
+		   token_string,
+		   message_prefix,
+		   message);
+    }
+  else if (expected_token == G_TOKEN_NONE)
+    {
+      if (print_unexp)
+	msg_handler (scanner,
+		     "unexpected %s%s%s",
+		     token_string,
+		     message_prefix,
+		     message);
+      else
+	msg_handler (scanner,
+		     "%s%s%s",
+		     token_string,
+		     message_prefix,
+		     message);
+    }
+  else
+    {
+      if (print_unexp)
+	msg_handler (scanner,
+		     "unexpected %s, expected %s%s%s",
+		     token_string,
+		     expected_string,
+		     message_prefix,
+		     message);
+      else
+	msg_handler (scanner,
+		     "%s, expected %s%s%s",
+		     token_string,
+		     expected_string,
+		     message_prefix,
+		     message);
+    }
+  
+  g_free (token_string);
+  g_free (expected_string);
+}
+
+static void
+json_scanner_get_token_i (JsonScanner	*scanner,
+		       GTokenType	*token_p,
+		       GTokenValue	*value_p,
+		       guint		*line_p,
+		       guint		*position_p)
+{
+  do
+    {
+      json_scanner_free_value (token_p, value_p);
+      json_scanner_get_token_ll (scanner, token_p, value_p, line_p, position_p);
+    }
+  while (((*token_p > 0 && *token_p < 256) &&
+	  strchr (scanner->config->cset_skip_characters, *token_p)) ||
+	 (*token_p == G_TOKEN_CHAR &&
+	  strchr (scanner->config->cset_skip_characters, value_p->v_char)) ||
+	 (*token_p == G_TOKEN_COMMENT_MULTI &&
+	  scanner->config->skip_comment_multi) ||
+	 (*token_p == G_TOKEN_COMMENT_SINGLE &&
+	  scanner->config->skip_comment_single));
+  
+  switch (*token_p)
+    {
+    case G_TOKEN_IDENTIFIER:
+      if (scanner->config->identifier_2_string)
+	*token_p = G_TOKEN_STRING;
+      break;
+      
+    case G_TOKEN_SYMBOL:
+      if (scanner->config->symbol_2_token)
+	*token_p = (GTokenType) value_p->v_symbol;
+      break;
+      
+    case G_TOKEN_BINARY:
+    case G_TOKEN_OCTAL:
+    case G_TOKEN_HEX:
+      if (scanner->config->numbers_2_int)
+	*token_p = G_TOKEN_INT;
+      break;
+      
+    default:
+      break;
+    }
+  
+  if (*token_p == G_TOKEN_INT &&
+      scanner->config->int_2_float)
+    {
+      *token_p = G_TOKEN_FLOAT;
+      if (scanner->config->store_int64)
+        {
+#ifdef _MSC_VER
+          /* work around error C2520, see gvaluetransform.c */
+          value_p->v_float = (__int64)value_p->v_int64;
+#else
+          value_p->v_float = value_p->v_int64;
+#endif
+        }
+      else
+	value_p->v_float = value_p->v_int;
+    }
+  
+  errno = 0;
+}
+
+static void
+json_scanner_get_token_ll (JsonScanner *scanner,
+                           GTokenType  *token_p,
+                           GTokenValue *value_p,
+                           guint       *line_p,
+                           guint       *position_p)
+{
+  JsonScannerConfig *config;
+  GTokenType	   token;
+  gboolean	   in_comment_multi;
+  gboolean	   in_comment_single;
+  gboolean	   in_string_sq;
+  gboolean	   in_string_dq;
+  GString	  *gstring;
+  GTokenValue	   value;
+  guchar	   ch;
+  
+  config = scanner->config;
+  (*value_p).v_int64 = 0;
+  
+  if ((scanner->text >= scanner->text_end && scanner->input_fd < 0) ||
+      scanner->token == G_TOKEN_EOF)
+    {
+      *token_p = G_TOKEN_EOF;
+      return;
+    }
+  
+  in_comment_multi = FALSE;
+  in_comment_single = FALSE;
+  in_string_sq = FALSE;
+  in_string_dq = FALSE;
+  gstring = NULL;
+  
+  do /* while (ch != 0) */
+    {
+      gboolean dotted_float = FALSE;
+      
+      ch = json_scanner_get_char (scanner, line_p, position_p);
+      
+      value.v_int64 = 0;
+      token = G_TOKEN_NONE;
+      
+      /* this is *evil*, but needed ;(
+       * we first check for identifier first character, because	 it
+       * might interfere with other key chars like slashes or numbers
+       */
+      if (config->scan_identifier &&
+	  ch && strchr (config->cset_identifier_first, ch))
+	goto identifier_precedence;
+      
+      switch (ch)
+	{
+	case 0:
+	  token = G_TOKEN_EOF;
+	  (*position_p)++;
+	  /* ch = 0; */
+	  break;
+	  
+	case '/':
+	  if (!config->scan_comment_multi ||
+	      json_scanner_peek_next_char (scanner) != '*')
+	    goto default_case;
+	  json_scanner_get_char (scanner, line_p, position_p);
+	  token = G_TOKEN_COMMENT_MULTI;
+	  in_comment_multi = TRUE;
+	  gstring = g_string_new (NULL);
+	  while ((ch = json_scanner_get_char (scanner, line_p, position_p)) != 0)
+	    {
+	      if (ch == '*' && json_scanner_peek_next_char (scanner) == '/')
+		{
+		  json_scanner_get_char (scanner, line_p, position_p);
+		  in_comment_multi = FALSE;
+		  break;
+		}
+	      else
+		gstring = g_string_append_c (gstring, ch);
+	    }
+	  ch = 0;
+	  break;
+	  
+	case '\'':
+	  if (!config->scan_string_sq)
+	    goto default_case;
+	  token = G_TOKEN_STRING;
+	  in_string_sq = TRUE;
+	  gstring = g_string_new (NULL);
+	  while ((ch = json_scanner_get_char (scanner, line_p, position_p)) != 0)
+	    {
+	      if (ch == '\'')
+		{
+		  in_string_sq = FALSE;
+		  break;
+		}
+	      else
+		gstring = g_string_append_c (gstring, ch);
+	    }
+	  ch = 0;
+	  break;
+	  
+	case '"':
+	  if (!config->scan_string_dq)
+	    goto default_case;
+	  token = G_TOKEN_STRING;
+	  in_string_dq = TRUE;
+	  gstring = g_string_new (NULL);
+	  while ((ch = json_scanner_get_char (scanner, line_p, position_p)) != 0)
+	    {
+	      if (ch == '"')
+		{
+		  in_string_dq = FALSE;
+		  break;
+		}
+	      else
+		{
+		  if (ch == '\\')
+		    {
+		      ch = json_scanner_get_char (scanner, line_p, position_p);
+		      switch (ch)
+			{
+			  guint	i;
+			  guint	fchar;
+			  
+			case 0:
+			  break;
+			  
+			case '\\':
+			  gstring = g_string_append_c (gstring, '\\');
+			  break;
+			  
+			case 'n':
+			  gstring = g_string_append_c (gstring, '\n');
+			  break;
+			  
+			case 't':
+			  gstring = g_string_append_c (gstring, '\t');
+			  break;
+			  
+			case 'r':
+			  gstring = g_string_append_c (gstring, '\r');
+			  break;
+			  
+			case 'b':
+			  gstring = g_string_append_c (gstring, '\b');
+			  break;
+			  
+			case 'f':
+			  gstring = g_string_append_c (gstring, '\f');
+			  break;
+
+                        case 'u':
+                          fchar = json_scanner_peek_next_char (scanner);
+                          if (is_hex_digit (fchar))
+                            {
+                              gunichar ucs;
+
+                              ucs = json_scanner_get_unichar (scanner, line_p, position_p);
+
+                              if (g_unichar_type (ucs) == G_UNICODE_SURROGATE)
+                                {
+                                  /* read next surrogate */
+                                  if ('\\' == json_scanner_get_char (scanner, line_p, position_p)
+                                      && 'u' == json_scanner_get_char (scanner, line_p, position_p))
+                                    {
+                                      gunichar ucs_lo = json_scanner_get_unichar (scanner, line_p, position_p);
+                                      g_assert (g_unichar_type (ucs_lo) == G_UNICODE_SURROGATE);
+                                      ucs = (((ucs & 0x3ff) << 10) | (ucs_lo & 0x3ff)) + 0x10000;
+                                    }
+                                }
+
+                              g_assert (g_unichar_validate (ucs));
+                              gstring = g_string_append_unichar (gstring, ucs);
+                            }
+                          break;
+			  
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			  i = ch - '0';
+			  fchar = json_scanner_peek_next_char (scanner);
+			  if (fchar >= '0' && fchar <= '7')
+			    {
+			      ch = json_scanner_get_char (scanner, line_p, position_p);
+			      i = i * 8 + ch - '0';
+			      fchar = json_scanner_peek_next_char (scanner);
+			      if (fchar >= '0' && fchar <= '7')
+				{
+				  ch = json_scanner_get_char (scanner, line_p, position_p);
+				  i = i * 8 + ch - '0';
+				}
+			    }
+			  gstring = g_string_append_c (gstring, i);
+			  break;
+			  
+			default:
+			  gstring = g_string_append_c (gstring, ch);
+			  break;
+			}
+		    }
+		  else
+		    gstring = g_string_append_c (gstring, ch);
+		}
+	    }
+	  ch = 0;
+	  break;
+	  
+	case '.':
+	  if (!config->scan_float)
+	    goto default_case;
+	  token = G_TOKEN_FLOAT;
+	  dotted_float = TRUE;
+	  ch = json_scanner_get_char (scanner, line_p, position_p);
+	  goto number_parsing;
+	  
+	case '$':
+	  if (!config->scan_hex_dollar)
+	    goto default_case;
+	  token = G_TOKEN_HEX;
+	  ch = json_scanner_get_char (scanner, line_p, position_p);
+	  goto number_parsing;
+	  
+	case '0':
+	  if (config->scan_octal)
+	    token = G_TOKEN_OCTAL;
+	  else
+	    token = G_TOKEN_INT;
+	  ch = json_scanner_peek_next_char (scanner);
+	  if (config->scan_hex && (ch == 'x' || ch == 'X'))
+	    {
+	      token = G_TOKEN_HEX;
+	      json_scanner_get_char (scanner, line_p, position_p);
+	      ch = json_scanner_get_char (scanner, line_p, position_p);
+	      if (ch == 0)
+		{
+		  token = G_TOKEN_ERROR;
+		  value.v_error = G_ERR_UNEXP_EOF;
+		  (*position_p)++;
+		  break;
+		}
+	      if (json_scanner_char_2_num (ch, 16) < 0)
+		{
+		  token = G_TOKEN_ERROR;
+		  value.v_error = G_ERR_DIGIT_RADIX;
+		  ch = 0;
+		  break;
+		}
+	    }
+	  else if (config->scan_binary && (ch == 'b' || ch == 'B'))
+	    {
+	      token = G_TOKEN_BINARY;
+	      json_scanner_get_char (scanner, line_p, position_p);
+	      ch = json_scanner_get_char (scanner, line_p, position_p);
+	      if (ch == 0)
+		{
+		  token = G_TOKEN_ERROR;
+		  value.v_error = G_ERR_UNEXP_EOF;
+		  (*position_p)++;
+		  break;
+		}
+	      if (json_scanner_char_2_num (ch, 10) < 0)
+		{
+		  token = G_TOKEN_ERROR;
+		  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+		  ch = 0;
+		  break;
+		}
+	    }
+	  else
+	    ch = '0';
+	  /* fall through */
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	number_parsing:
+	{
+          gboolean in_number = TRUE;
+	  gchar *endptr;
+	  
+	  if (token == G_TOKEN_NONE)
+	    token = G_TOKEN_INT;
+	  
+	  gstring = g_string_new (dotted_float ? "0." : "");
+	  gstring = g_string_append_c (gstring, ch);
+	  
+	  do /* while (in_number) */
+	    {
+	      gboolean is_E;
+	      
+	      is_E = token == G_TOKEN_FLOAT && (ch == 'e' || ch == 'E');
+	      
+	      ch = json_scanner_peek_next_char (scanner);
+	      
+	      if (json_scanner_char_2_num (ch, 36) >= 0 ||
+		  (config->scan_float && ch == '.') ||
+		  (is_E && (ch == '+' || ch == '-')))
+		{
+		  ch = json_scanner_get_char (scanner, line_p, position_p);
+		  
+		  switch (ch)
+		    {
+		    case '.':
+		      if (token != G_TOKEN_INT && token != G_TOKEN_OCTAL)
+			{
+			  value.v_error = token == G_TOKEN_FLOAT ? G_ERR_FLOAT_MALFORMED : G_ERR_FLOAT_RADIX;
+			  token = G_TOKEN_ERROR;
+			  in_number = FALSE;
+			}
+		      else
+			{
+			  token = G_TOKEN_FLOAT;
+			  gstring = g_string_append_c (gstring, ch);
+			}
+		      break;
+		      
+		    case '0':
+		    case '1':
+		    case '2':
+		    case '3':
+		    case '4':
+		    case '5':
+		    case '6':
+		    case '7':
+		    case '8':
+		    case '9':
+		      gstring = g_string_append_c (gstring, ch);
+		      break;
+		      
+		    case '-':
+		    case '+':
+		      if (token != G_TOKEN_FLOAT)
+			{
+			  token = G_TOKEN_ERROR;
+			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+			  in_number = FALSE;
+			}
+		      else
+			gstring = g_string_append_c (gstring, ch);
+		      break;
+		      
+		    case 'e':
+		    case 'E':
+		      if ((token != G_TOKEN_HEX && !config->scan_float) ||
+			  (token != G_TOKEN_HEX &&
+			   token != G_TOKEN_OCTAL &&
+			   token != G_TOKEN_FLOAT &&
+			   token != G_TOKEN_INT))
+			{
+			  token = G_TOKEN_ERROR;
+			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+			  in_number = FALSE;
+			}
+		      else
+			{
+			  if (token != G_TOKEN_HEX)
+			    token = G_TOKEN_FLOAT;
+			  gstring = g_string_append_c (gstring, ch);
+			}
+		      break;
+		      
+		    default:
+		      if (token != G_TOKEN_HEX)
+			{
+			  token = G_TOKEN_ERROR;
+			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+			  in_number = FALSE;
+			}
+		      else
+			gstring = g_string_append_c (gstring, ch);
+		      break;
+		    }
+		}
+	      else
+		in_number = FALSE;
+	    }
+	  while (in_number);
+	  
+	  endptr = NULL;
+	  if (token == G_TOKEN_FLOAT)
+	    value.v_float = g_strtod (gstring->str, &endptr);
+	  else
+	    {
+	      guint64 ui64 = 0;
+	      switch (token)
+		{
+		case G_TOKEN_BINARY:
+		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 2);
+		  break;
+		case G_TOKEN_OCTAL:
+		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 8);
+		  break;
+		case G_TOKEN_INT:
+		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 10);
+		  break;
+		case G_TOKEN_HEX:
+		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 16);
+		  break;
+		default: ;
+		}
+	      if (scanner->config->store_int64)
+		value.v_int64 = ui64;
+	      else
+		value.v_int = ui64;
+	    }
+	  if (endptr && *endptr)
+	    {
+	      token = G_TOKEN_ERROR;
+	      if (*endptr == 'e' || *endptr == 'E')
+		value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+	      else
+		value.v_error = G_ERR_DIGIT_RADIX;
+	    }
+	  g_string_free (gstring, TRUE);
+	  gstring = NULL;
+	  ch = 0;
+	} /* number_parsing:... */
+	break;
+	
+	default:
+	default_case:
+	{
+	  if (config->cpair_comment_single &&
+	      ch == config->cpair_comment_single[0])
+	    {
+	      token = G_TOKEN_COMMENT_SINGLE;
+	      in_comment_single = TRUE;
+	      gstring = g_string_new (NULL);
+	      ch = json_scanner_get_char (scanner, line_p, position_p);
+	      while (ch != 0)
+		{
+		  if (ch == config->cpair_comment_single[1])
+		    {
+		      in_comment_single = FALSE;
+		      ch = 0;
+		      break;
+		    }
+		  
+		  gstring = g_string_append_c (gstring, ch);
+		  ch = json_scanner_get_char (scanner, line_p, position_p);
+		}
+	      /* ignore a missing newline at EOF for single line comments */
+	      if (in_comment_single &&
+		  config->cpair_comment_single[1] == '\n')
+		in_comment_single = FALSE;
+	    }
+	  else if (config->scan_identifier && ch &&
+		   strchr (config->cset_identifier_first, ch))
+	    {
+	    identifier_precedence:
+	      
+	      if (config->cset_identifier_nth && ch &&
+		  strchr (config->cset_identifier_nth,
+			  json_scanner_peek_next_char (scanner)))
+		{
+		  token = G_TOKEN_IDENTIFIER;
+		  gstring = g_string_new (NULL);
+		  gstring = g_string_append_c (gstring, ch);
+		  do
+		    {
+		      ch = json_scanner_get_char (scanner, line_p, position_p);
+		      gstring = g_string_append_c (gstring, ch);
+		      ch = json_scanner_peek_next_char (scanner);
+		    }
+		  while (ch && strchr (config->cset_identifier_nth, ch));
+		  ch = 0;
+		}
+	      else if (config->scan_identifier_1char)
+		{
+		  token = G_TOKEN_IDENTIFIER;
+		  value.v_identifier = g_new0 (gchar, 2);
+		  value.v_identifier[0] = ch;
+		  ch = 0;
+		}
+	    }
+	  if (ch)
+	    {
+	      if (config->char_2_token)
+		token = ch;
+	      else
+		{
+		  token = G_TOKEN_CHAR;
+		  value.v_char = ch;
+		}
+	      ch = 0;
+	    }
+	} /* default_case:... */
+	break;
+	}
+      g_assert (ch == 0 && token != G_TOKEN_NONE); /* paranoid */
+    }
+  while (ch != 0);
+  
+  if (in_comment_multi || in_comment_single ||
+      in_string_sq || in_string_dq)
+    {
+      token = G_TOKEN_ERROR;
+      if (gstring)
+	{
+	  g_string_free (gstring, TRUE);
+	  gstring = NULL;
+	}
+      (*position_p)++;
+      if (in_comment_multi || in_comment_single)
+	value.v_error = G_ERR_UNEXP_EOF_IN_COMMENT;
+      else /* (in_string_sq || in_string_dq) */
+	value.v_error = G_ERR_UNEXP_EOF_IN_STRING;
+    }
+  
+  if (gstring)
+    {
+      value.v_string = g_string_free (gstring, FALSE);
+      gstring = NULL;
+    }
+  
+  if (token == G_TOKEN_IDENTIFIER)
+    {
+      if (config->scan_symbols)
+	{
+	  JsonScannerKey *key;
+	  guint scope_id;
+	  
+	  scope_id = scanner->scope_id;
+	  key = json_scanner_lookup_internal (scanner, scope_id, value.v_identifier);
+	  if (!key && scope_id && scanner->config->scope_0_fallback)
+	    key = json_scanner_lookup_internal (scanner, 0, value.v_identifier);
+	  
+	  if (key)
+	    {
+	      g_free (value.v_identifier);
+	      token = G_TOKEN_SYMBOL;
+	      value.v_symbol = key->value;
+	    }
+	}
+      
+      if (token == G_TOKEN_IDENTIFIER &&
+	  config->scan_identifier_NULL &&
+	  strlen (value.v_identifier) == 4)
+	{
+	  gchar *null_upper = "NULL";
+	  gchar *null_lower = "null";
+	  
+	  if (scanner->config->case_sensitive)
+	    {
+	      if (value.v_identifier[0] == null_upper[0] &&
+		  value.v_identifier[1] == null_upper[1] &&
+		  value.v_identifier[2] == null_upper[2] &&
+		  value.v_identifier[3] == null_upper[3])
+		token = G_TOKEN_IDENTIFIER_NULL;
+	    }
+	  else
+	    {
+	      if ((value.v_identifier[0] == null_upper[0] ||
+		   value.v_identifier[0] == null_lower[0]) &&
+		  (value.v_identifier[1] == null_upper[1] ||
+		   value.v_identifier[1] == null_lower[1]) &&
+		  (value.v_identifier[2] == null_upper[2] ||
+		   value.v_identifier[2] == null_lower[2]) &&
+		  (value.v_identifier[3] == null_upper[3] ||
+		   value.v_identifier[3] == null_lower[3]))
+		token = G_TOKEN_IDENTIFIER_NULL;
+	    }
+	}
+    }
+  
+  *token_p = token;
+  *value_p = value;
+}
diff --git a/src/glib-jsonrpc/json-glib/json-scanner.h b/src/glib-jsonrpc/json-glib/json-scanner.h
new file mode 100644
index 0000000..49d7b1e
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-scanner.h
@@ -0,0 +1,171 @@
+/* json-scanner.h: Tokenizer for JSON
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2008 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * JsonScanner is a specialized tokenizer for JSON adapted from
+ * the GScanner tokenizer in GLib; GScanner came with this notice:
+ * 
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ *
+ * JsonScanner: modified by Emmanuele Bassi <ebassi openedhand com>
+ */
+
+#ifndef __JSON_SCANNER_H__
+#define __JSON_SCANNER_H__
+
+#include <glib/gdataset.h>
+#include <glib/ghash.h>
+#include <glib/gscanner.h>
+
+G_BEGIN_DECLS
+
+typedef struct _JsonScanner       JsonScanner;
+typedef struct _JsonScannerConfig JsonScannerConfig;
+
+typedef void (* JsonScannerMsgFunc) (JsonScanner *scanner,
+                                     gchar       *message,
+                                     gboolean     is_error);
+
+/**
+ * JsonTokenType:
+ * @JSON_TOKEN_INVALID: marker
+ * @JSON_TOKEN_TRUE: symbol for 'true' bareword
+ * @JSON_TOKEN_FALSE: symbol for 'false' bareword
+ * @JSON_TOKEN_NULL: symbol for 'null' bareword
+ * @JSON_TOKEN_VAR: symbol for 'var' bareword
+ * @JSON_TOKEN_LAST: marker
+ *
+ * Tokens for JsonScanner-based parser, extending #GTokenType.
+ */
+typedef enum {
+  JSON_TOKEN_INVALID = G_TOKEN_LAST,
+
+  JSON_TOKEN_TRUE,
+  JSON_TOKEN_FALSE,
+  JSON_TOKEN_NULL,
+  JSON_TOKEN_VAR,
+
+  JSON_TOKEN_LAST
+} JsonTokenType;
+
+/**
+ * JsonScanner:
+ *
+ * Tokenizer scanner for JSON. See #GScanner
+ *
+ * Since: 0.6
+ */
+struct _JsonScanner
+{
+  /*< private >*/
+  /* unused fields */
+  gpointer user_data;
+  guint max_parse_errors;
+  
+  /* json_scanner_error() increments this field */
+  guint parse_errors;
+  
+  /* name of input stream, featured by the default message handler */
+  const gchar *input_name;
+  
+  /* quarked data */
+  GData *qdata;
+  
+  /* link into the scanner configuration */
+  JsonScannerConfig *config;
+  
+  /* fields filled in after json_scanner_get_next_token() */
+  GTokenType token;
+  GTokenValue value;
+  guint line;
+  guint position;
+  
+  /* fields filled in after json_scanner_peek_next_token() */
+  GTokenType next_token;
+  GTokenValue next_value;
+  guint next_line;
+  guint next_position;
+  
+  /* to be considered private */
+  GHashTable *symbol_table;
+  gint input_fd;
+  const gchar *text;
+  const gchar *text_end;
+  gchar *buffer;
+  guint scope_id;
+  
+  /* handler function for _warn and _error */
+  JsonScannerMsgFunc msg_handler;
+};
+
+JsonScanner *json_scanner_new                  (void);
+void         json_scanner_destroy              (JsonScanner *scanner);
+void         json_scanner_input_file           (JsonScanner *scanner,
+                                                gint         input_fd);
+void         json_scanner_sync_file_offset     (JsonScanner *scanner);
+void         json_scanner_input_text           (JsonScanner *scanner,
+                                                const gchar *text,
+                                                guint        text_len);
+GTokenType   json_scanner_get_next_token       (JsonScanner *scanner);
+GTokenType   json_scanner_peek_next_token      (JsonScanner *scanner);
+GTokenType   json_scanner_cur_token            (JsonScanner *scanner);
+GTokenValue  json_scanner_cur_value            (JsonScanner *scanner);
+guint        json_scanner_cur_line             (JsonScanner *scanner);
+guint        json_scanner_cur_position         (JsonScanner *scanner);
+gboolean     json_scanner_eof                  (JsonScanner *scanner);
+guint        json_scanner_set_scope            (JsonScanner *scanner,
+                                                guint        scope_id);
+void         json_scanner_scope_add_symbol     (JsonScanner *scanner,
+                                                guint        scope_id,
+                                                const gchar *symbol,
+                                                gpointer     value);
+void         json_scanner_scope_remove_symbol  (JsonScanner *scanner,
+                                                guint        scope_id,
+                                                const gchar *symbol);
+gpointer     json_scanner_scope_lookup_symbol  (JsonScanner *scanner,
+                                                guint        scope_id,
+                                                const gchar *symbol);
+void         json_scanner_scope_foreach_symbol (JsonScanner *scanner,
+                                                guint        scope_id,
+                                                GHFunc       func,
+                                                gpointer     user_data);
+gpointer     json_scanner_lookup_symbol        (JsonScanner *scanner,
+                                                const gchar *symbol);
+void         json_scanner_unexp_token          (JsonScanner *scanner,
+                                                GTokenType   expected_token,
+                                                const gchar *identifier_spec,
+                                                const gchar *symbol_spec,
+                                                const gchar *symbol_name,
+                                                const gchar *message,
+                                                gint         is_error);
+void         json_scanner_error                (JsonScanner *scanner,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2,3);
+void         json_scanner_warn                 (JsonScanner *scanner,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2,3);
+
+G_END_DECLS
+
+#endif /* __JSON_SCANNER_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-serializable.c b/src/glib-jsonrpc/json-glib/json-serializable.c
new file mode 100644
index 0000000..e49ccb1
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-serializable.c
@@ -0,0 +1,341 @@
+/* json-gobject.c - JSON GObject integration
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi openedhand com>
+ */
+
+/**
+ * SECTION:json-serializable
+ * @short_description: Interface for serialize and deserialize special GObjects
+ *
+ * #JsonSerializable is an interface for #GObject classes that
+ * allows controlling how the class is going to be serialized
+ * or deserialized by json_construct_gobject() and
+ * json_serialize_gobject() respectively.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "json-types-private.h"
+#include "json-gobject-private.h"
+#include "json-debug.h"
+
+/**
+ * json_serializable_serialize_property:
+ * @serializable: a #JsonSerializable object
+ * @property_name: the name of the property
+ * @value: the value of the property
+ * @pspec: a #GParamSpec
+ *
+ * Asks a #JsonSerializable implementation to serialize a #GObject
+ * property into a #JsonNode object.
+ *
+ * Return value: a #JsonNode containing the serialized property
+ */
+JsonNode *
+json_serializable_serialize_property (JsonSerializable *serializable,
+                                      const gchar      *property_name,
+                                      const GValue     *value,
+                                      GParamSpec       *pspec)
+{
+  JsonSerializableIface *iface;
+
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
+  g_return_val_if_fail (property_name != NULL, NULL);
+  g_return_val_if_fail (value != NULL, NULL);
+  g_return_val_if_fail (pspec != NULL, NULL);
+
+  iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
+
+  return iface->serialize_property (serializable, property_name, value, pspec);
+}
+
+/**
+ * json_serializable_deserialize_property:
+ * @serializable: a #JsonSerializable
+ * @property_name: the name of the property
+ * @value: (out): a pointer to an uninitialized #GValue
+ * @pspec: a #GParamSpec
+ * @property_node: a #JsonNode containing the serialized property
+ *
+ * Asks a #JsonSerializable implementation to deserialize the
+ * property contained inside @property_node into @value.
+ *
+ * Return value: %TRUE if the property was successfully deserialized.
+ */
+gboolean
+json_serializable_deserialize_property (JsonSerializable *serializable,
+                                        const gchar      *property_name,
+                                        GValue           *value,
+                                        GParamSpec       *pspec,
+                                        JsonNode         *property_node)
+{
+  JsonSerializableIface *iface;
+
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), FALSE);
+  g_return_val_if_fail (property_name != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (property_node != NULL, FALSE);
+
+  iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
+
+  return iface->deserialize_property (serializable,
+                                      property_name,
+                                      value,
+                                      pspec,
+                                      property_node);
+}
+
+static gboolean
+json_serializable_real_deserialize (JsonSerializable *serializable,
+                                    const gchar      *name,
+                                    GValue           *value,
+                                    GParamSpec       *pspec,
+                                    JsonNode         *node)
+{
+  JSON_NOTE (GOBJECT, "Default deserialization for property '%s'", pspec->name);
+  return json_deserialize_pspec (value, pspec, node);
+}
+
+static JsonNode *
+json_serializable_real_serialize (JsonSerializable *serializable,
+                                  const gchar      *name,
+                                  const GValue     *value,
+                                  GParamSpec       *pspec)
+{
+  JSON_NOTE (GOBJECT, "Default serialization for property '%s'", pspec->name);
+
+  if (g_param_value_defaults (pspec, (GValue *)value))
+    return NULL;
+
+  return json_serialize_pspec (value, pspec);
+}
+
+static GParamSpec *
+json_serializable_real_find_property (JsonSerializable *serializable,
+                                      const char       *name)
+{
+  return g_object_class_find_property (G_OBJECT_GET_CLASS (serializable), name);
+}
+
+static GParamSpec **
+json_serializable_real_list_properties (JsonSerializable *serializable,
+                                        guint            *n_pspecs)
+{
+  return g_object_class_list_properties (G_OBJECT_GET_CLASS (serializable), n_pspecs);
+}
+
+static void
+json_serializable_real_set_property (JsonSerializable *serializable,
+                                     GParamSpec       *pspec,
+                                     const GValue     *value)
+{
+  g_object_set_property (G_OBJECT (serializable), pspec->name, value);
+}
+
+static void
+json_serializable_real_get_property (JsonSerializable *serializable,
+                                     GParamSpec       *pspec,
+                                     GValue           *value)
+{
+  g_object_get_property (G_OBJECT (serializable), pspec->name, value);
+}
+
+/* typedef to satisfy G_DEFINE_INTERFACE's naming */
+typedef JsonSerializableIface   JsonSerializableInterface;
+
+static void
+json_serializable_default_init (JsonSerializableInterface *iface)
+{
+  iface->serialize_property = json_serializable_real_serialize;
+  iface->deserialize_property = json_serializable_real_deserialize;
+  iface->find_property = json_serializable_real_find_property;
+  iface->list_properties = json_serializable_real_list_properties;
+  iface->set_property = json_serializable_real_set_property;
+  iface->get_property = json_serializable_real_get_property;
+}
+
+G_DEFINE_INTERFACE (JsonSerializable, json_serializable, G_TYPE_OBJECT);
+
+/**
+ * json_serializable_default_serialize_property:
+ * @serializable: a #JsonSerializable object
+ * @property_name: the name of the property
+ * @value: the value of the property
+ * @pspec: a #GParamSpec
+ *
+ * Calls the default implementation of the #JsonSerializable
+ * serialize_property() virtual function
+ *
+ * This function can be used inside a custom implementation
+ * of the serialize_property() virtual function in lieu of:
+ *
+ * |[
+ *   JsonSerializable *iface;
+ *   JsonNode *node;
+ *
+ *   iface = g_type_default_interface_peek (JSON_TYPE_SERIALIZABLE);
+ *   node = iface->serialize_property (serializable, property_name,
+ *                                     value,
+ *                                     pspec);
+ * ]|
+ *
+ * Return value: (transfer full): a #JsonNode containing the serialized
+ *   property
+ *
+ * Since: 0.10
+ */
+JsonNode *
+json_serializable_default_serialize_property (JsonSerializable *serializable,
+                                              const gchar      *property_name,
+                                              const GValue     *value,
+                                              GParamSpec       *pspec)
+{
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
+  g_return_val_if_fail (property_name != NULL, NULL);
+  g_return_val_if_fail (value != NULL, NULL);
+  g_return_val_if_fail (pspec != NULL, NULL);
+
+  return json_serializable_real_serialize (serializable,
+                                           property_name,
+                                           value, pspec);
+}
+
+/**
+ * json_serializable_default_deserialize_property:
+ * @serializable: a #JsonSerializable
+ * @property_name: the name of the property
+ * @value: a pointer to an uninitialized #GValue
+ * @pspec: a #GParamSpec
+ * @property_node: a #JsonNode containing the serialized property
+ *
+ * Calls the default implementation of the #JsonSerializable
+ * deserialize_property() virtual function
+ *
+ * This function can be used inside a custom implementation
+ * of the deserialize_property() virtual function in lieu of:
+ *
+ * |[
+ *   JsonSerializable *iface;
+ *   gboolean res;
+ *
+ *   iface = g_type_default_interface_peek (JSON_TYPE_SERIALIZABLE);
+ *   res = iface->deserialize_property (serializable, property_name,
+ *                                      value,
+ *                                      pspec,
+ *                                      property_node);
+ * ]|
+ *
+ * Return value: %TRUE if the property was successfully deserialized.
+ *
+ * Since: 0.10
+ */
+gboolean
+json_serializable_default_deserialize_property (JsonSerializable *serializable,
+                                                const gchar      *property_name,
+                                                GValue           *value,
+                                                GParamSpec       *pspec,
+                                                JsonNode         *property_node)
+{
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), FALSE);
+  g_return_val_if_fail (property_name != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+  g_return_val_if_fail (pspec != NULL, FALSE);
+  g_return_val_if_fail (property_node != NULL, FALSE);
+
+  return json_serializable_real_deserialize (serializable,
+                                             property_name,
+                                             value, pspec,
+                                             property_node);
+}
+
+/**
+ * json_serializable_find_property:
+ * @serializable: a #JsonSerializable
+ * @name: the name of the property
+ *
+ * FIXME
+ *
+ * Return value: (transfer none): the #GParamSpec for the property
+ *   or %NULL if no property was found
+ *
+ * Since: 0.14
+ */
+GParamSpec *
+json_serializable_find_property (JsonSerializable *serializable,
+                                 const char       *name)
+{
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  return JSON_SERIALIZABLE_GET_IFACE (serializable)->find_property (serializable, name);
+}
+
+/**
+ * json_serializable_list_properties:
+ * @serializable: a #JsonSerializable
+ * @n_pspecs: (out): return location for the length of the array
+ *   of #GParamSpec returned by the function
+ *
+ * FIXME
+ *
+ * Return value: (array length=n_pspecs) (transfer container): an array
+ *   of #GParamSpec. Use g_free() to free the array when done.
+ *
+ * Since: 0.14
+ */
+GParamSpec **
+json_serializable_list_properties (JsonSerializable *serializable,
+                                   guint            *n_pspecs)
+{
+  g_return_val_if_fail (JSON_IS_SERIALIZABLE (serializable), NULL);
+
+  return JSON_SERIALIZABLE_GET_IFACE (serializable)->list_properties (serializable, n_pspecs);
+}
+
+void
+json_serializable_set_property (JsonSerializable *serializable,
+                                GParamSpec       *pspec,
+                                const GValue     *value)
+{
+  g_return_if_fail (JSON_IS_SERIALIZABLE (serializable));
+  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (value != NULL);
+
+  JSON_SERIALIZABLE_GET_IFACE (serializable)->set_property (serializable,
+                                                            pspec,
+                                                            value);
+}
+
+void
+json_serializable_get_property (JsonSerializable *serializable,
+                                GParamSpec       *pspec,
+                                GValue           *value)
+{
+  g_return_if_fail (JSON_IS_SERIALIZABLE (serializable));
+  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (value != NULL);
+
+  JSON_SERIALIZABLE_GET_IFACE (serializable)->get_property (serializable,
+                                                            pspec,
+                                                            value);
+}
diff --git a/src/glib-jsonrpc/json-glib/json-types-private.h b/src/glib-jsonrpc/json-glib/json-types-private.h
new file mode 100644
index 0000000..e7f73f2
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-types-private.h
@@ -0,0 +1,66 @@
+/* json-types-private.h - JSON data types private header
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#ifndef __JSON_TYPES_PRIVATE_H__
+#define __JSON_TYPES_PRIVATE_H__
+
+#include "json-types.h"
+
+G_BEGIN_DECLS
+
+struct _JsonNode
+{
+  /*< private >*/
+  JsonNodeType type;
+
+  union {
+    JsonObject *object;
+    JsonArray *array;
+    GValue value;
+  } data;
+
+  JsonNode *parent;
+};
+
+struct _JsonArray
+{
+  GPtrArray *elements;
+
+  volatile gint ref_count;
+};
+
+struct _JsonObject
+{
+  GHashTable *members;
+
+  /* the members of the object, ordered in reverse */
+  GList *members_ordered;
+
+  volatile gint ref_count;
+};
+
+const gchar *json_node_type_get_name (JsonNodeType node_type);
+
+G_END_DECLS
+
+#endif /* __JSON_TYPES_PRIVATE_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-types.h b/src/glib-jsonrpc/json-glib/json-types.h
new file mode 100644
index 0000000..ecbf198
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-types.h
@@ -0,0 +1,334 @@
+/* json-types.h - JSON data types
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_TYPES_H__
+#define __JSON_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * JSON_NODE_TYPE:
+ * @node: a #JsonNode
+ *
+ * Evaluates to the #JsonNodeType contained by @node
+ */
+#define JSON_NODE_TYPE(node)    (json_node_get_node_type ((node)))
+
+/**
+ * JSON_NODE_HOLDS:
+ * @node: a #JsonNode
+ * @t: a #JsonNodeType
+ *
+ * Evaluates to %TRUE if the @node holds type @t
+ *
+ * Since: 0.10
+ */
+#define JSON_NODE_HOLDS(node,t)         (json_node_get_node_type ((node)) == (t))
+
+/**
+ * JSON_NODE_HOLDS_VALUE:
+ * @node: a #JsonNode
+ *
+ * Evaluates to %TRUE if @node holds a %JSON_NODE_VALUE
+ *
+ * Since: 0.10
+ */
+#define JSON_NODE_HOLDS_VALUE(node)     (JSON_NODE_HOLDS ((node), JSON_NODE_VALUE))
+
+/**
+ * JSON_NODE_HOLDS_OBJECT:
+ * @node: a #JsonNode
+ *
+ * Evaluates to %TRUE if @node holds a %JSON_NODE_OBJECT
+ *
+ * Since: 0.10
+ */
+#define JSON_NODE_HOLDS_OBJECT(node)    (JSON_NODE_HOLDS ((node), JSON_NODE_OBJECT))
+
+/**
+ * JSON_NODE_HOLDS_ARRAY:
+ * @node: a #JsonNode
+ *
+ * Evaluates to %TRUE if @node holds a %JSON_NODE_ARRAY
+ *
+ * Since: 0.10
+ */
+#define JSON_NODE_HOLDS_ARRAY(node)     (JSON_NODE_HOLDS ((node), JSON_NODE_ARRAY))
+
+/**
+ * JSON_NODE_HOLDS_NULL:
+ * @node: a #JsonNode
+ *
+ * Evaluates to %TRUE if @node holds a %JSON_NODE_NULL
+ *
+ * Since: 0.10
+ */
+#define JSON_NODE_HOLDS_NULL(node)      (JSON_NODE_HOLDS ((node), JSON_NODE_NULL))
+
+#define JSON_TYPE_NODE          (json_node_get_type ())
+#define JSON_TYPE_OBJECT        (json_object_get_type ())
+#define JSON_TYPE_ARRAY         (json_array_get_type ())
+
+/**
+ * JsonNode:
+ *
+ * A generic container of JSON data types. The contents of the #JsonNode
+ * structure are private and should only be accessed via the provided
+ * functions and never directly.
+ */
+typedef struct _JsonNode        JsonNode;
+
+/**
+ * JsonObject:
+ *
+ * A JSON object type. The contents of the #JsonObject structure are private
+ * and should only be accessed by the provided API
+ */
+typedef struct _JsonObject      JsonObject;
+
+/**
+ * JsonArray:
+ *
+ * A JSON array type. The contents of the #JsonArray structure are private
+ * and should only be accessed by the provided API
+ */
+typedef struct _JsonArray       JsonArray;
+
+/**
+ * JsonNodeType:
+ * @JSON_NODE_OBJECT: The node contains a #JsonObject
+ * @JSON_NODE_ARRAY: The node contains a #JsonArray
+ * @JSON_NODE_VALUE: The node contains a fundamental type
+ * @JSON_NODE_NULL: Special type, for nodes containing null
+ *
+ * Indicates the content of a #JsonNode.
+ */
+typedef enum {
+  JSON_NODE_OBJECT,
+  JSON_NODE_ARRAY,
+  JSON_NODE_VALUE,
+  JSON_NODE_NULL
+} JsonNodeType;
+
+/**
+ * JsonObjectForeach:
+ * @object: the iterated #JsonObject
+ * @member_name: the name of the member
+ * @member_node: a #JsonNode containing the @member_name value
+ * @user_data: data passed to the function
+ *
+ * The function to be passed to json_object_foreach_member(). You
+ * should not add or remove members to and from @object within
+ * this function. It is safe to change the value of @member_node.
+ *
+ * Since: 0.8
+ */
+typedef void (* JsonObjectForeach) (JsonObject  *object,
+                                    const gchar *member_name,
+                                    JsonNode    *member_node,
+                                    gpointer     user_data);
+
+/**
+ * JsonArrayForeach:
+ * @array: the iterated #JsonArray
+ * @index_: the index of the element
+ * @element_node: a #JsonNode containing the value at @index_
+ * @user_data: data passed to the function
+ *
+ * The function to be passed to json_array_foreach_element(). You
+ * should not add or remove elements to and from @array within
+ * this function. It is safe to change the value of @element_node.
+ *
+ * Since: 0.8
+ */
+typedef void (* JsonArrayForeach) (JsonArray  *array,
+                                   guint       index_,
+                                   JsonNode   *element_node,
+                                   gpointer    user_data);
+
+/*
+ * JsonNode
+ */
+GType                 json_node_get_type        (void) G_GNUC_CONST;
+JsonNode *            json_node_new             (JsonNodeType  type);
+JsonNode *            json_node_copy            (JsonNode     *node);
+void                  json_node_free            (JsonNode     *node);
+JsonNodeType          json_node_get_node_type   (JsonNode     *node);
+GType                 json_node_get_value_type  (JsonNode     *node);
+void                  json_node_set_parent      (JsonNode     *node,
+                                                 JsonNode     *parent);
+JsonNode *            json_node_get_parent      (JsonNode     *node);
+const gchar *         json_node_type_name       (JsonNode     *node);
+
+void                  json_node_set_object      (JsonNode     *node,
+                                                 JsonObject   *object);
+void                  json_node_take_object     (JsonNode     *node,
+                                                 JsonObject   *object);
+JsonObject *          json_node_get_object      (JsonNode     *node);
+JsonObject *          json_node_dup_object      (JsonNode     *node);
+void                  json_node_set_array       (JsonNode     *node,
+                                                 JsonArray    *array);
+void                  json_node_take_array      (JsonNode     *node,
+                                                 JsonArray    *array);
+JsonArray *           json_node_get_array       (JsonNode     *node);
+JsonArray *           json_node_dup_array       (JsonNode     *node);
+void                  json_node_set_value       (JsonNode     *node,
+                                                 const GValue *value);
+void                  json_node_get_value       (JsonNode     *node,
+                                                 GValue       *value);
+void                  json_node_set_string      (JsonNode     *node,
+                                                 const gchar  *value);
+const gchar *         json_node_get_string      (JsonNode     *node);
+gchar *               json_node_dup_string      (JsonNode     *node);
+void                  json_node_set_int         (JsonNode     *node,
+                                                 gint64        value);
+gint64                json_node_get_int         (JsonNode     *node);
+void                  json_node_set_double      (JsonNode     *node,
+                                                 gdouble       value);
+gdouble               json_node_get_double      (JsonNode     *node);
+void                  json_node_set_boolean     (JsonNode     *node,
+                                                 gboolean      value);
+gboolean              json_node_get_boolean     (JsonNode     *node);
+gboolean              json_node_is_null         (JsonNode     *node);
+
+/*
+ * JsonObject
+ */
+GType                 json_object_get_type           (void) G_GNUC_CONST;
+JsonObject *          json_object_new                (void);
+JsonObject *          json_object_ref                (JsonObject  *object);
+void                  json_object_unref              (JsonObject  *object);
+
+#ifndef JSON_DISABLE_DEPRECATED
+void                  json_object_add_member         (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonNode    *node) G_GNUC_DEPRECATED;
+#endif /* JSON_DISABLE_DEPRECATED */
+
+void                  json_object_set_member         (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonNode    *node);
+void                  json_object_set_int_member     (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gint64       value);
+void                  json_object_set_double_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gdouble      value);
+void                  json_object_set_boolean_member (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      gboolean     value);
+void                  json_object_set_string_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      const gchar *value);
+void                  json_object_set_null_member    (JsonObject  *object,
+                                                      const gchar *member_name);
+void                  json_object_set_array_member   (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonArray   *value);
+void                  json_object_set_object_member  (JsonObject  *object,
+                                                      const gchar *member_name,
+                                                      JsonObject  *value);
+GList *               json_object_get_members        (JsonObject  *object);
+JsonNode *            json_object_get_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonNode *            json_object_dup_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+gint64                json_object_get_int_member     (JsonObject  *object,
+                                                      const gchar *member_name);
+gdouble               json_object_get_double_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_get_boolean_member (JsonObject  *object,
+                                                      const gchar *member_name);
+const gchar *         json_object_get_string_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_get_null_member    (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonArray *           json_object_get_array_member   (JsonObject  *object,
+                                                      const gchar *member_name);
+JsonObject *          json_object_get_object_member  (JsonObject  *object,
+                                                      const gchar *member_name);
+gboolean              json_object_has_member         (JsonObject  *object,
+                                                      const gchar *member_name);
+void                  json_object_remove_member      (JsonObject  *object,
+                                                      const gchar *member_name);
+GList *               json_object_get_values         (JsonObject  *object);
+guint                 json_object_get_size           (JsonObject  *object);
+void                  json_object_foreach_member     (JsonObject  *object,
+                                                      JsonObjectForeach func,
+                                                      gpointer     data);
+
+GType                 json_array_get_type            (void) G_GNUC_CONST;
+JsonArray *           json_array_new                 (void);
+JsonArray *           json_array_sized_new           (guint        n_elements);
+JsonArray *           json_array_ref                 (JsonArray   *array);
+void                  json_array_unref               (JsonArray   *array);
+void                  json_array_add_element         (JsonArray   *array,
+                                                      JsonNode    *node);
+void                  json_array_add_int_element     (JsonArray   *array,
+                                                      gint64       value);
+void                  json_array_add_double_element  (JsonArray   *array,
+                                                      gdouble      value);
+void                  json_array_add_boolean_element (JsonArray   *array,
+                                                      gboolean     value);
+void                  json_array_add_string_element  (JsonArray   *array,
+                                                      const gchar *value);
+void                  json_array_add_null_element    (JsonArray   *array);
+void                  json_array_add_array_element   (JsonArray   *array,
+                                                      JsonArray   *value);
+void                  json_array_add_object_element  (JsonArray   *array,
+                                                      JsonObject  *value);
+GList *               json_array_get_elements        (JsonArray   *array);
+JsonNode *            json_array_get_element         (JsonArray   *array,
+                                                      guint        index_);
+gint64                json_array_get_int_element     (JsonArray   *array,
+                                                      guint        index_);
+gdouble               json_array_get_double_element  (JsonArray   *array,
+                                                      guint        index_);
+gboolean              json_array_get_boolean_element (JsonArray   *array,
+                                                      guint        index_);
+const gchar *         json_array_get_string_element  (JsonArray   *array,
+                                                      guint        index_);
+gboolean              json_array_get_null_element    (JsonArray   *array,
+                                                      guint        index_);
+JsonArray *           json_array_get_array_element   (JsonArray   *array,
+                                                      guint        index_);
+JsonObject *          json_array_get_object_element  (JsonArray   *array,
+                                                      guint        index_);
+JsonNode *            json_array_dup_element         (JsonArray   *array,
+                                                      guint        index_);
+void                  json_array_remove_element      (JsonArray   *array,
+                                                      guint        index_);
+guint                 json_array_get_length          (JsonArray   *array);
+void                  json_array_foreach_element     (JsonArray   *array,
+                                                      JsonArrayForeach func,
+                                                      gpointer     data);
+
+G_END_DECLS
+
+#endif /* __JSON_TYPES_H__ */
diff --git a/src/glib-jsonrpc/json-glib/json-version.h b/src/glib-jsonrpc/json-glib/json-version.h
new file mode 100644
index 0000000..cfda093
--- /dev/null
+++ b/src/glib-jsonrpc/json-glib/json-version.h
@@ -0,0 +1,100 @@
+/* json-version.h - JSON-GLib versioning information
+ * 
+ * This file is part of JSON-GLib
+ * Copyright (C) 2007  OpenedHand Ltd.
+ * Copyright (C) 2009  Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Emmanuele Bassi  <ebassi linux intel com>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_VERSION_H__
+#define __JSON_VERSION_H__
+
+/**
+ * SECTION:json-version
+ * @short_description: JSON-GLib version checking
+ *
+ * JSON-GLib provides macros to check the version of the library
+ * at compile-time
+ */
+
+/**
+ * JSON_MAJOR_VERSION:
+ *
+ * Json major version component (e.g. 1 if %JSON_VERSION is 1.2.3)
+ */
+#define JSON_MAJOR_VERSION              (0)
+
+/**
+ * JSON_MINOR_VERSION:
+ *
+ * Json minor version component (e.g. 2 if %JSON_VERSION is 1.2.3)
+ */
+#define JSON_MINOR_VERSION              (14)
+
+/**
+ * JSON_MICRO_VERSION:
+ *
+ * Json micro version component (e.g. 3 if %JSON_VERSION is 1.2.3)
+ */
+#define JSON_MICRO_VERSION              (0)
+
+/**
+ * JSON_VERSION
+ *
+ * Json version.
+ */
+#define JSON_VERSION                    (0.14.0)
+
+/**
+ * JSON_VERSION_S:
+ *
+ * Json version, encoded as a string, useful for printing and
+ * concatenation.
+ */
+#define JSON_VERSION_S                  "0.14.0"
+
+/**
+ * JSON_VERSION_HEX:
+ *
+ * Json version, encoded as an hexadecimal number, useful for
+ * integer comparisons.
+ */
+#define JSON_VERSION_HEX                (JSON_MAJOR_VERSION << 24 | \
+                                         JSON_MINOR_VERSION << 16 | \
+                                         JSON_MICRO_VERSION << 8)
+
+/**
+ * JSON_CHECK_VERSION:
+ * @major: required major version
+ * @minor: required minor version
+ * @micro: required micro version
+ *
+ * Compile-time version checking. Evaluates to %TRUE if the version
+ * of Json is greater than the required one.
+ */
+#define JSON_CHECK_VERSION(major,minor,micro)   \
+        (JSON_MAJOR_VERSION > (major) || \
+         (JSON_MAJOR_VERSION == (major) && JSON_MINOR_VERSION > (minor)) || \
+         (JSON_MAJOR_VERSION == (major) && JSON_MINOR_VERSION == (minor) && \
+          JSON_MICRO_VERSION >= (micro)))
+
+#endif /* __JSON_VERSION_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]