Flax Engine: GWT client-side JSON serialization and deserialization
During the design document stage of the Flax Game Engine we came up against a wall when trying to communicate information between the engine, the editor and networked clients, so we explored XML and JSON as data formats to communicate the information.
Requirement Analysis
The main data that needed to be communicated between the engine and the editor was that of the Map object. The Map editor would create a FMap object through the user interfacing with it and constructing the map graphically. This map contains information about the tiles, objects, npc’s etc. All these objects needed to be saved into a data format which could be read easily by engine.
We also needed to allow for changes to the default classes such as tiles, objects and entities, so that you could extend the default type and add new member etc., which meant that the format, or rather, our code needed to be dynamic. Parsing something like XML won’t work as it needs to be predefined, you must know what data is in what node and what members of the class want the data. Other factors such as file size ruled out XML, especially for the networking component. JSON strings can be passed between server and client faster then XML.
The only method that provides this kind of functionality is serialization, i.e creating JSON strings from our Java objects. Now remember I am talking about GWT here, not simply JavaScript, so it’s not as simple to convert objects into JSON strings. Serializing objects in Java is a simple task, though with Google Web Toolkit, not so much. Lucky after much searching and experimenting with libraries I found gwtprojsonserializer which uses deferred binding, Google Web Toolkit’s answer to Java reflection which is needed for serialization.
GWT Pro JSON Serializer
This Library offers the functionality which I speak of above. You can find the repository here. First a big thanks to kfuntak who wrote the library and many thanks to matthias.buchner who modified the library and fixed errors in the code. Ah, the power of open source. You can download a working jar file of the libary here.
How to use gwtprojsonserializer
I will take a simple example to explain how to use this library as the documentation for its use on the Google code repository is somewhat vague.
First, we will setup a simple 3D Vector class with 3 members, which has 2 constructors, one with no parameters (which is required for the deserialization process) and a constructor that takes in 3 parameters. Also all members have set and get methods. These again are required for both the serialization and deserialization of the class. The class also implements the JsonSerializable interface to mark it as a class which can be serialised and, of course, the imports from the gwtprojsonserializer.
package flax.sampleCode.client; import com.google.gwt.core.client.GWT; import com.kfuntak.gwt.json.serialization.client.JsonSerializable; import com.kfuntak.gwt.json.serialization.client.Serializer; public class Vector3D implements JsonSerializable { private double x; private double y; private double z; public Vector3D(double x, double y, double z) { super(); this.x = x; this.y = y; this.z = z; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } public double getZ() { return z; } public void setZ(double z) { this.z = z; } /** * A constructor with no parameters is required */ public Vector3D() { super(); } }
So now we have our class setup we can now add the methods for converting the object to a JSON string and from a JSON string to an Object. Add the following methods to the class.
/** * Pass this method JSON and it gives you back an object which you can * then assign to your object via MyObject x = JsonToObject(String Json); * * @param JSON * @return */ public static Vector3D JsonToObject(String Json) { Serializer serializer = (Serializer) GWT.create(Serializer.class); return (Vector3D)serializer.deSerialize(Json,"flax.sampleCode.client.Vector3D"); } /** * Creates a JSON string from the current object * * @return String of JSON */ public String toJson() { Serializer serializer = (Serializer) GWT.create(Serializer.class); return serializer.serialize(this); }
The first method is a static method which returns an object of the Vector3D. See the code below to see how that method can be used to populate objects with data. The second method serializes the object and returns the JSON string. Check out the below code for it in action. If you would like to experiment with the code sample you can download the Eclipse project here.
package flax.sampleCode.client; import com.google.gwt.core.client.EntryPoint; public class SampleCode implements EntryPoint { Vector3D vectorOne = new Vector3D(100, 100, 30); Vector3D vectorTwo = null; @Override public void onModuleLoad() { // Converts the object to a JSON string String JSON = vectorOne.toJson(); System.out.println("JSON string of the vectorOne object \n" + JSON); //Populates the null object with data from the JSON string vectorTwo = Vector3D.JsonToObject(JSON); System.out.println("\n VectorTwo X = " + vectorTwo.getX()); System.out.println(" VectorTwo Y = " + vectorTwo.getY()); System.out.println(" VectorTwo Z = " + vectorTwo.getZ()); } }
[ad#adsence_inline_banner_468*60]
9 Comments
Trackbacks for this post
-
[…] This post was mentioned on Twitter by Hacker News YC, Hacker News, Dr Carl Lange, Dr Carl Lange, Flax.ie and others. Flax.ie said: Ciarán just posted an article on GWT client-side JSON serialization and deserialization http://t.co/1PUHNq9 […]
-
[…] Flax Engine: GWT client-side JSON serialization and deserialization […]
-
[…] Flax Engine: GWT client-side JSON serialization and deserialization […]
Hey there, nice writeup! But what about using overlay-types to work with JSON data?[0, 1] Have you tried that? Would be interesting to know since we are looking for a nice JSON abstraction ourselfs..
BTW. I think that fromJSON(String json) is a better name that JsonToObject(String json) since this ain’t no C# 😉 (and it fits nicely with toJSON())
[0]: http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSON.html
[1]: http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsOverlay.html
Hey Seb, yes I have searched for hours on end exploring various different solutions and have come across overlay-types. Though that method wouldn’t really work for us. As the FMap object is quite complex, with 3 lists of objects which themselves are complex. Its been a while since i looked at overlay-types, but I believe it also required predefined data which we could not provide, as we wanted more flexibility.
Yes I actually originally had the method named that way, though changed it for some reason, but I think your right it would be better that way.
Thanks for the comment
Seb,
Using the overlay types are better for very simple data structures. However, if you are looking for serialization and de-serialization of complex structures (for instance with nested objects), I would go with a specific library.
I also like the fact I can see the content of an instance when I am debugging in my IDE. I could not get that easily when using the overlay types.
gwtprojsonserializer is a pretty complex library. There are many other libraries trying to do the same thing but none were maintained when I was looking for one. I was very surprised I could not find that built-in GWT.
Matthias
In case you’re interested: I’ve written another JSON mapper which also comes with XML support. Feel free to take a look at it and give feedback
http://code.google.com/p/piriti/
– Harald
Hey Harald,
yes i have used piriti before, but it didn’t really suit the task, thanks anyway.
Nice one! thanks