#include #include #include #include "searpc-utils.h" json_t *json_serialize_pspec (const GValue *value) { /* Only types in json-glib but G_TYPE_BOXED */ switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value))) { case G_TYPE_STRING: if (!g_value_get_string (value)) break; else return json_string(g_value_get_string(value)); case G_TYPE_BOOLEAN: return json_boolean(g_value_get_boolean(value)); case G_TYPE_INT: return json_integer(g_value_get_int(value)); case G_TYPE_UINT: return json_integer(g_value_get_uint(value)); case G_TYPE_LONG: return json_integer(g_value_get_long(value)); case G_TYPE_ULONG: return json_integer(g_value_get_ulong(value)); case G_TYPE_INT64: return json_integer(g_value_get_int64(value)); case G_TYPE_FLOAT: return json_real(g_value_get_float(value)); case G_TYPE_DOUBLE: return json_real(g_value_get_double(value)); case G_TYPE_CHAR: return json_integer(g_value_get_schar(value)); case G_TYPE_UCHAR: return json_integer(g_value_get_uchar(value)); case G_TYPE_ENUM: return json_integer(g_value_get_enum(value)); case G_TYPE_FLAGS: return json_integer(g_value_get_flags(value)); case G_TYPE_NONE: break; case G_TYPE_OBJECT: { GObject *object = g_value_get_object(value); if (object) return json_gobject_serialize(object); } break; defalut: g_warning("Unsuppoted type `%s'",g_type_name(G_VALUE_TYPE(value))); } return json_null(); } json_t *json_gobject_serialize (GObject *gobject) { json_t *object = json_object(); GParamSpec **pspecs; guint n_pspecs, i; pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (gobject), &n_pspecs); for (i=0;i!=n_pspecs;++i) { json_t *node; GParamSpec *pspec = pspecs[i]; GValue value = { 0, }; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_object_get_property(gobject, pspec->name, &value); node=json_serialize_pspec (&value); if (node) json_object_set_new (object, pspec->name, node); g_value_unset (&value); } g_free (pspecs); return object; } gboolean json_deserialize_pspec (GValue *value, GParamSpec *pspec, json_t *node) { switch (json_typeof(node)) { case JSON_OBJECT: if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT)) { GObject *object; object = json_gobject_deserialize (G_VALUE_TYPE (value), node); if (object) g_value_take_object (value, object); else g_value_set_object (value, NULL); return TRUE; } break; case JSON_STRING: if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING) { g_value_set_string(value, json_string_value(node)); return TRUE; } break; case JSON_INTEGER: { json_int_t int_value = json_integer_value (node); switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value))) { case G_TYPE_CHAR: g_value_set_schar(value, (gchar)int_value); return TRUE; case G_TYPE_UCHAR: g_value_set_uchar (value, (guchar)int_value); return TRUE; case G_TYPE_INT: g_value_set_int (value, (gint)int_value); return TRUE; case G_TYPE_UINT: g_value_set_uint(value, (guint)int_value); return TRUE; case G_TYPE_LONG: g_value_set_long(value, (glong)int_value); return TRUE; case G_TYPE_ULONG: g_value_set_ulong(value, (gulong)int_value); return TRUE; case G_TYPE_INT64: g_value_set_int64(value,(gint64)int_value); return TRUE; case G_TYPE_ENUM: g_value_set_enum(value,(gint64)int_value); return TRUE; case G_TYPE_FLAGS: g_value_set_flags(value,(gint64)int_value); return TRUE; } } break; case JSON_REAL: { double real_value = json_real_value(node); switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value))) { case G_TYPE_FLOAT: g_value_set_float(value,(gfloat)real_value); return TRUE; case G_TYPE_DOUBLE: g_value_set_double(value,(gdouble)real_value); return TRUE; } } break; case JSON_TRUE: case JSON_FALSE: if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_BOOLEAN) { g_value_set_boolean(value,(gboolean)json_is_true(node)); return TRUE; } break; case JSON_NULL: if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_STRING) { g_value_set_string (value, NULL); return TRUE; } else if (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)) == G_TYPE_OBJECT) { g_value_set_object (value, NULL); return TRUE; } } return FALSE; } GObject *json_gobject_deserialize (GType gtype, json_t *object) { GObjectClass *klass; GObject *ret; guint n_members, i; json_t *val; 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); json_object_foreach(object,member_name,val) { GParamSpec *pspec; GParameter param = { NULL, }; 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(¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (json_deserialize_pspec (¶m.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 (¶m.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 (¶m->value); } g_array_free(construct_params, TRUE); g_type_class_unref(klass); return ret; }