/** * 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 GObject * json_gobject_new (GType gtype, JsonObject *object) { JsonSerializableIface *iface = NULL; JsonSerializable *serializable = NULL; gboolean deserialize_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 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; 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, 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 (¶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); iface = JSON_SERIALIZABLE_GET_IFACE (serializable); deserialize_property = (iface->deserialize_property != NULL); } else deserialize_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; pspec = g_object_class_find_property (klass, member_name); if (!pspec) continue; /* 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)) continue; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); val = json_object_get_member (object, member_name); if (deserialize_property) { res = iface->deserialize_property (serializable, pspec->name, &value, pspec, val); } 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); g_value_unset (&value); } g_list_free (members); g_object_thaw_notify (retval); g_type_class_unref (klass); return retval; }