Ejemplo n.º 1
0
/**
 * 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);
}
Ejemplo n.º 2
0
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 (&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_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);
      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;
}