Re: [Vala] De/serializing Classes into Json



On Thu, 2013-02-07 at 17:24 +0100, Johann Weging wrote:
Hello,

I'm trying to de/serialize a Vala class into Json with the glib-json-1.0 module.
A class like:

public class testClass : GLib.Object {
  public int i{get;set;}
  public int[] array {get;set;}
}

After setting some values the class should be serialized into:

{
  i : 1,
  array : [1,2,3]
}

What I tried so far:

Using the "object_to_data" and "object_from_data" function of glib-josn.

The problem is, that this function seems to skip arrays.
The array is not returned by "list_properties" function of the "ObjectClass" class. Furthermore the two 
function store the properties without its name. The result actually looks like:

{
  i : 1
}

I have tried to marshal the class myself, that's how I noticed arrays are not returned by "list_properties".

I tried to add support for array by using the "get_data" function of the "GLib.Object". This function 
doesn't return data. Used it like this:

// build class and set values:

int j = testclass.get_data("i");
int j = testclass.get_data<int>("i");

I don't want to reimplement the array marshaling for every new class I build.

Is there any nice way to marshal array into json with a function that looks something like this:

array_to_data(Type baseType, array, [maybe add needed extraflags]);

Well, you could do something like this (untested):

        public Json.Array array_to_data<T> (T[] array) {
          Json.Array res = new Json.Array.sized (array.length);
          int i;
        
          if ( typeof (T) == typeof (int) ) {
            unowned int[] int_array = (int[]) array;
            for ( i = 0 ; i < int_array.length ; i++ ) {
              res.add_int_element (int_array[i]);
            }
          } else if ( typeof (T) == typeof (bool) ) {
            unowned bool[] bool_array = (bool[]) array;
            for ( i = 0 ; i < bool_array.length ; i++ ) {
              res.add_boolean_element (bool_array[i]);
            }
          } else if ( typeof (T) == typeof (double) ) {
            unowned double[] double_array = (double[]) array;
            for ( i = 0 ; i < double_array.length ; i++ ) {
              res.add_double_element (double_array[i]);
            }
          }
        
          return res;
        }

Obviously you'll want to add support for whatever types you want to
use... and probably Json.Serializable as well.

or even integrate it into "Json.object_to_data()" and "Json.object_from_data()". 

Not AFAIK, at least not without some work on the json-glib side of
things.  With the exception of strings, arrays aren't supported by
json-glib.  According to [1]:

        "Simple GObject classes can be (de)serialized into JSON objects,
        if the properties have compatible types with the native JSON
        types (integers, booleans, strings, string vectors). If the
        class to be (de)serialized has complex data types for properties
        (like boxed types or other objects) then the class should
        implement the provided JsonSerializable interface and its
        virtual functions."

The only arrays which are registered GObject properties are arrays of
strings (which have their own GType).

Unfortunately there isn't a lot that can be done by either json-glib or
Vala.  It's simply not possible to register GObject properties for
arrays, and the containers in GLib (HashTable, Array, List, etc.) don't
actually include any run-time type information.

The containers in libgee, on the other hand, do include run-time type
information.  If you're willing to write some code it should be possible
to add support to json-glib for libgee containers.  I doubt they want a
hard dependency on libgee, but they might be willing to add support for
a GModule-based solution...  if you're interested, you should talk to
the json-glib maintainer.


-Evan


[1]
http://developer.gnome.org/json-glib/unstable/json-glib-GObject-Serialization.html





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]