[json-glib] gobject: Support constructor properties
- From: Emmanuele Bassi <ebassi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [json-glib] gobject: Support constructor properties
- Date: Tue, 27 Oct 2009 14:10:40 +0000 (UTC)
commit 83dea3b3dd2281dca206e0873b5fed0a2a3d50de
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Tue Oct 27 14:01:24 2009 +0000
gobject: Support constructor properties
The GObject deserialization code currently skips all the constructor
and constructor-only properties. In order to implement them we can
add a preliminary pass on the JSON object members and build a
GParameter array.
As we don't have a GObject instance we cannot really use the
Serializable interface to provide custom parsing for complex data
structures, thus we fall back to the default deserialization code
path.
json-glib/json-gobject.c | 98 ++++++++++++++++++++++++++++++++++++++-----
tests/test-serialize-full.c | 11 +++--
2 files changed, 93 insertions(+), 16 deletions(-)
---
diff --git a/json-glib/json-gobject.c b/json-glib/json-gobject.c
index 1b3b1fe..f10b6a3 100644
--- a/json-glib/json-gobject.c
+++ b/json-glib/json-gobject.c
@@ -187,14 +187,90 @@ json_gobject_new (GType gtype,
JsonSerializableIface *iface = NULL;
JsonSerializable *serializable = NULL;
gboolean deserialize_property;
- GList *members, *l;
+ GList *members, *members_left, *l;
guint n_members;
GObjectClass *klass;
GObject *retval;
+ GArray *construct_params;
+ gint n, i;
klass = g_type_class_ref (gtype);
- retval = g_object_new (gtype, NULL);
+ n_members = json_object_get_size (object);
+ members = json_object_get_members (object);
+ members_left = NULL;
+
+ /* first pass: construct and 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;
+ GValue value = { 0, };
+ gboolean res = FALSE;
+
+ pspec = g_object_class_find_property (klass, member_name);
+ if (!pspec)
+ goto next_member;
+
+ if (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY) ||
+ !(pspec->flags & G_PARAM_CONSTRUCT_ONLY))
+ goto next_member;
+
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ goto next_member;
+
+ g_value_init (¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+
+ val = json_object_get_member (object, member_name);
+ res = json_deserialize_pspec (¶m.value, pspec, val);
+ if (!res)
+ g_value_unset (¶m.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, pspec->name);
+ }
+
+ 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 (¶m->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);
@@ -206,9 +282,6 @@ json_gobject_new (GType gtype,
g_object_freeze_notify (retval);
- n_members = json_object_get_size (object);
- members = json_object_get_members (object);
-
for (l = members; l != NULL; l = l->next)
{
const gchar *member_name = l->data;
@@ -221,7 +294,9 @@ json_gobject_new (GType gtype,
if (!pspec)
continue;
- if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+ /* we should have dealt with these above */
+ if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) ||
+ (pspec->flags & G_PARAM_CONSTRUCT))
continue;
if (!(pspec->flags & G_PARAM_WRITABLE))
@@ -242,6 +317,9 @@ json_gobject_new (GType gtype,
if (!res)
res = json_deserialize_pspec (&value, pspec, val);
+ /* FIXME - we probably want to be able to have a custom
+ * set_property() for Serializable implementations
+ */
if (res)
g_object_set_property (retval, pspec->name, &value);
@@ -492,7 +570,7 @@ json_serialize_pspec (const GValue *real_value,
break;
case G_TYPE_STRING:
- /* strings might be NULL */
+ /* strings might be NULL, so we handle it differently */
if (!g_value_get_string (real_value))
retval = json_node_new (JSON_NODE_NULL);
else
@@ -536,8 +614,7 @@ json_serialize_pspec (const GValue *real_value,
}
else
{
- g_warning ("Unsupported type `%s'",
- g_type_name (G_VALUE_TYPE (real_value)));
+ g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
}
break;
@@ -595,8 +672,7 @@ json_serialize_pspec (const GValue *real_value,
break;
default:
- g_warning ("Unsupported type `%s'",
- g_type_name (G_VALUE_TYPE (real_value)));
+ g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value)));
break;
}
diff --git a/tests/test-serialize-full.c b/tests/test-serialize-full.c
index 443b41f..7c42dbd 100644
--- a/tests/test-serialize-full.c
+++ b/tests/test-serialize-full.c
@@ -297,7 +297,8 @@ test_object_class_init (TestObjectClass *klass)
PROP_BAR,
g_param_spec_boolean ("bar", "Bar", "Bar",
FALSE,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_BAZ,
g_param_spec_string ("baz", "Baz", "Baz",
@@ -330,7 +331,7 @@ static void
test_object_init (TestObject *object)
{
object->foo = 0;
- object->bar = TRUE;
+ object->bar = FALSE;
object->baz = NULL;
object->blah.foo = object->foo;
@@ -346,7 +347,7 @@ test_object_init (TestObject *object)
static const gchar *var_test =
"{\n"
" \"foo\" : 42,\n"
-" \"bar\" : false,\n"
+" \"bar\" : true,\n"
" \"baz\" : \"hello\",\n"
" \"meh\" : \"baz\",\n"
" \"mah\" : [ \"hello\", \", \", \"world\", \"!\" ],\n"
@@ -377,12 +378,12 @@ test_deserialize (void)
" baz: %s\n"
" meh: %s\n",
TEST_OBJECT (object)->foo == 42 ? "<true>" : "<false>",
- TEST_OBJECT (object)->bar == FALSE ? "<true>" : "<false>",
+ TEST_OBJECT (object)->bar == TRUE ? "<true>" : "<false>",
TEST_OBJECT (object)->baz != NULL ? "<true>" : "<false>",
TEST_OBJECT (object)->meh == TEST_ENUM_BAZ ? "<true>" : "<false>");
g_assert_cmpint (TEST_OBJECT (object)->foo, ==, 42);
- g_assert_cmpint (TEST_OBJECT (object)->bar, ==, FALSE);
+ g_assert_cmpint (TEST_OBJECT (object)->bar, ==, TRUE);
g_assert_cmpstr (TEST_OBJECT (object)->baz, ==, "hello");
g_assert_cmpint (TEST_OBJECT (object)->meh, ==, TEST_ENUM_BAZ);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]