Beispiel #1
0
GObject *json_gobject_deserialize (GType gtype, json_t *object)
{
    GObjectClass *klass;
    GObject *ret;
    guint n_members, i;
    json_t *head, *member;
    const char *member_name;
    GArray *construct_params;

    klass = g_type_class_ref (gtype);
    n_members = json_object_size (object);
    construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
    head = json_object_iter (object);

    for (member=head; member; member=json_object_iter_next (object, member)) {
        GParamSpec *pspec;
        GParameter param = { NULL, };
        const char *member_name = json_object_iter_key (member);
        json_t *val = json_object_iter_value(member);

        pspec = g_object_class_find_property (klass, member_name);

        if (!pspec)
            continue;

        if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
            continue;

        if (!(pspec->flags & G_PARAM_WRITABLE))
            continue;

        g_value_init(&param.value, G_PARAM_SPEC_VALUE_TYPE (pspec));

        if (json_deserialize_pspec (&param.value, pspec, val)) {
            param.name = g_strdup (pspec->name);
            g_array_append_val (construct_params, param);
        }
        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 (&param.value)), g_type_name (gtype));
    }

    ret = g_object_newv (gtype, construct_params->len, (GParameter *) construct_params->data);

    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_type_class_unref(klass);

    return ret;

}
Beispiel #2
0
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);
}
Beispiel #3
0
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 = json_serializable_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;
}