59

I am looking for a simple Json (de)serializer for Java that might work with GWT. I have googled a bit and found some solutions that either require annotate every member or define useless interfaces. Quite a boring. Why don't we have something really simple like

class MyBean {
    ...
}

new GoodSerializer().makeString(new MyBean());
new GoodSerializer().makeObject("{ ... }", MyBean.class)
amartynov
  • 4,125
  • 2
  • 31
  • 35

13 Answers13

56

Take a look at GWT's Overlay Types. I think this is by far the easiest way to work with JSON in GWT. Here's a modified code example from the linked article:

public class Customer extends JavaScriptObject {
    public final native String getFirstName() /*-{ 
        return this.first_name;
    }-*/;
    public final native void setFirstName(String value) /*-{
        this.first_name = value;
    }-*/;
    public final native String getLastName() /*-{
        return this.last_name;
    }-*/;
    public final native void setLastName(String value) /*-{
        this.last_name = value;
    }-*/;
}

Once you have the overlay type defined, it's easy to create a JavaScript object from JSON and access its properties in Java:

public static final native Customer buildCustomer(String json) /*-{
    return eval('(' + json + ')');
}-*/;

If you want the JSON representation of the object again, you can wrap the overlay type in a JSONObject:

Customer customer = buildCustomer("{'Bart', 'Simpson'}");
customer.setFirstName("Lisa");
// Displays {"first_name":"Lisa","last_name":"Simpson"}
Window.alert(new JSONObject(customer).toString());
Chris Kentfield
  • 1,652
  • 12
  • 9
  • 2
    The main issue I have with overlay types is that they mean you can't use the same object representations on the java side as you do on the GWT side. But I haven't found a better deserialization solution. – mooreds Nov 16 '09 at 22:42
  • 2
    I believe the best would be to annotate getters and have (de)serialization methods generated at compile time – skrat Dec 04 '09 at 11:36
  • 1
    Why not just use GWT's built-in JSON libraries? http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/json/client/ Or was this not yet available at the time this question was asked? I'll add and answer, below. – Eric Nguyen Jul 17 '10 at 04:59
  • @mooreds You can. You can have your GWT JSO implement an interface, but it must be the only type to delare this interface and you must annotate this interface with @SingleJsoImpl. You can then reuse the interface on the server side. – Mark Renouf Jul 24 '10 at 23:14
  • 1
    Looks like the annotation isn't needed anymore: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/e8415e6c5dbce14b/18b73b1c6641957f?lnk=gst&q=SingleJsoImpl#18b73b1c6641957f – mooreds Sep 02 '10 at 03:32
  • It would be nice if SO had [nested syntax highlighting](http://meta.stackexchange.com/q/203205/205238) ... – barfuin Apr 02 '14 at 08:26
  • Very cool. Here is the updated link: http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsOverlay.html – Nathan Dunn Apr 24 '16 at 19:46
38

Another thing to try is the new AutoBean framework introduced with GWT 2.1.

You define interfaces for your beans and a factory that vends them, and GWT generates implementations for you.

interface MyBean {
  String getFoo();
  void setFoo(String foo);
}

interface MyBiggerBean {
  List<MyBean> getBeans();
  void setBeans(List<MyBean> beans>;
}

interface Beanery extends AutoBeanFactory{
  AutoBean<MyBean> makeBean();
  AutoBean<MyBiggerBean> makeBigBean();
}

Beanery beanFactory = GWT.create(Beanery.class);

void go() {
  MyBean bean = beanFactory.makeBean().as();
  bean.setFoo("Hello, beans");
}

The AutoBeanCodex can be used to serialize them to and from json.

AutoBean<MyBean> autoBean = AutoBeanUtils.getAutoBean(bean);
String asJson = AutoBeanCodex.encode(autoBean).getPayload();

AutoBean<MyBean> autoBeanCloneAB = 
  AutoBeanCodex.decode(beanFactory, MyBean.class, asJson );

MyBean autoBeanClone = autoBeanCloneAB.as(); 
assertTrue(AutoBeanUtils.deepEquals(autoBean, autoBeanClone));

They work on the server side too — use AutoBeanFactoryMagic.create(Beanery.class) instead of GWT.create(Beanery.class).

Boris Daich
  • 2,431
  • 3
  • 23
  • 27
rjrjr
  • 489
  • 4
  • 4
  • 1
    If you are having DTO on the server side and you want to reuse your interfaces, AutoBean is definetly the best way for you. Thank you rjrjr, it saved my life... (or at least few hours) – zdenda.online Sep 11 '12 at 13:57
  • This requires using interfaces and pojos on the non gwt server. Is there a pure Jackson compatible pojo solution? – itaifrenkel Nov 11 '12 at 02:11
  • You can use AutoBean within GWT client and create JSON with the framework you like. It plain JSON on the network. – Christian Kuetbach Nov 12 '12 at 14:01
  • If I could upvote this more than once, I would. Superb solution to what was a difficult problem. – Spedge May 14 '13 at 13:23
12

The simplest way would be to use GWT's built-in JSON API. Here's the documentation. And here is a great tutorial on how to use it.

It's as simple as this:

String json = //json string
JSONValue value = JSONParser.parse(json);

The JSONValue API is pretty cool. It lets you chain validations as you extract values from the JSON object so that exceptions will be thrown if anything's amiss with the format.

Eric Nguyen
  • 40,312
  • 4
  • 25
  • 31
11

It seems that I found the right answer to my question

I figured out that bean to json and json to bean conversion in GWT isn't a trivial task. Known libraries would not work because GWT would require their full source code and this source code must use only Java classes that are amoung emulated by GWT. Also, you cannot use reflection in GWT. Very tough requirements!

I found the only existing solution named gwt-jsonizer. It uses a custom Generator class and requires a satellite interface for each "jsonable" bean. Unfortunately, it does not work without patching on the latest version of GWT and has not been updated for a long time.

So, I personally decided that it is cheaper and faster to make my beans khow how to convert themselves to and from json. Like this:

public class SmartBean {
    private String name;

    public String getName() { return name; }
    public void setName(String value) { name = value;  }

    public JSONObject toJson() {
        JSONObject result = new JSONObject();
        result.put("name", new JSONString(this.name));
        return result;
    }
    public void fromJson(JSONObject value) {
        this.name = value.get("name").isString().stringValue();
    }

}

JSONxxxx are GWT built-in classes that provide low-level json support.

amartynov
  • 4,125
  • 2
  • 31
  • 35
  • Interesting. This seems like bit of a short-coming with GWT to me. But it is good to know there is a way. I may need to do this in future myself, as we have a dashboard app written using GWT. – StaxMan Mar 31 '09 at 18:10
  • Yeah, this is why they ended up developing a built-in GWT JSON parser. http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/json/client/ I added a more complete answer, as well. – Eric Nguyen Jul 17 '10 at 05:11
  • 1
    This should be marked as the answer, as it is the cleanest way and doesn't relay on any non-core GWT libraries to complete. – Jason Washo Aug 11 '16 at 02:36
6

RestyGWT is a powerful library for encoding or decoding Java Object to JSON in GWT:

import javax.ws.rs.POST;
...
public interface PizzaOrderCodec extends JsonEncoderDecoder<PizzaOrder> {
}

Then:

// GWT will implement the interface for you
PizzaOrderCodec codec = GWT.create(PizzaOrderCodec.class);

// Encoding an object to json
PizzaOrder order = ... 
JSONValue json = codec.encode(order);

// decoding an object to from json
PizzaOrder other = codec.decode(json);

It has also got several easy to use API for consuming Restful web services.

Have a nice time.

Saeed Zarinfam
  • 9,818
  • 7
  • 59
  • 72
5

Check this:

GWT Professional JSON Serializer: http://code.google.com/p/gwtprojsonserializer/

!Works with GWT 2.0+!

  • At this point, the state-of-the art is GWT's built-in JSON parser. http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/json/client/ I added a more complete answer, as well. – Eric Nguyen Jul 17 '10 at 05:11
  • The question was about serialization, not parsing... – Mark Renouf Jul 24 '10 at 23:15
3

json.org/java seems to be included with GWT these days:

gwt-servlet-deps.jar\org\json\

Or, this project seems to be comprehensive: http://code.google.com/p/piriti/

Phaedrus
  • 487
  • 7
  • 15
  • 2
    I think right now (as of date of this comment) Piriti and RestyGWT are the two best solutions. RestyGWT is much less invasive than Piriti, but Piriti seems to be more robust. – sksamuel Jan 22 '11 at 11:15
2

In Google Web Toolkit Applications, pages 510 to 522, the author, Ryan Dewsbury, shows how to use GWT code generation to do serialization to and from XML and JSON documents.

You can download the code here; you want the chapter 10 code bundles, and then you want to look in the src/com/gwtapps/serialization package. I did not see a license for this code, but have emailed the author to see what he says. I'll update this if he replies.

Issues with this solution:

  • You have to add a marker interface on all your objects that you want serialized (he uses java.io.Serializable but I imagine you could use others--if you are using hibernate for your backend, your pojos might already be tagged like this).
  • The code only supports string properties; it could be extended.
  • The code is only written for 1.4 and 1.5.

So, this is not an out of the box solution, but a great starting point for someone to build a JSON serializer that fits with GWT. Combine that with a JSON serializer on the server side, like json-lib and you're good to go.

I also found this project (again, some marker interface is required).

mooreds
  • 4,932
  • 2
  • 32
  • 40
1

Try this serializer from Google Code: http://code.google.com/p/json-io/

If you need to write or read JSON format in Java, this is the tool to use. No need to create extra classes, etc. Convert a Java object graph to JSON format in one call. Do the opposite - create a JSON String or Stream to Java objects. This is the fastest library I have seen yet to do this. It is faster than ObjectOutputStream and ObjectInputStream in most cases, which use binary format.

Very handy utility.

John
  • 31
  • 2
1

You may want to checkout this project https://gerrit.googlesource.com/gwtjsonrpc/

It's a library created in order to support a code review system for Android, Gerrit, but it's a stand-alone module meant to be embedded into any GWT project, not just Gerrit.

A reasonable tutorial is probably the README in the top level of the directory. It's quite similar to standard GWT RPC but it uses JSON encoding. It also has built-in XSRF protection.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Bruno Bossola
  • 1,128
  • 1
  • 13
  • 24
0

I seem to be answering this question a lot...

There's a page on code.google.com titled Using GWT for JSON Mashups. It's (unfortunately) way over my head, as I'm not that familiar with GWT, so it may not be helpful.

James Moore
  • 8,636
  • 5
  • 71
  • 90
Powerlord
  • 87,612
  • 17
  • 125
  • 175
-1

OK, I deleted my previous answer because it turned out to be exactly what you didn't want.

I don't know how well it works with GWT, but we use the json-lib library to serialize objects in a normal Java project where I work.

It can create a JSONObject directly from a JavaBean, then use the resulting JSONObject's toString() method to get the actual JSON string back.

Likewise, it can also turn JSON back into a JavaBean.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
-1

Not sure if Jackson would work for you. I don't know if there's GWT-specific you are looking for; if not it should work.

But its serialization/deserialization works quite well, like:

// read json, create object
ObjectMapper mapper = new ObjectMapper();
MyBean bean = mapper.readValue(jsonAsString, MyBean.class);

// and write out
StringWriter sw = new StringWriter();
mapper.writeValue(sw, user);
String jsonOut = sw.toString();

You do need accessors (getX() to serialize, setX() to deserialize; can annotate methods with other names), but that's about it.

Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • 4
    Jackson is a great tool, but it can't cross compiled by GWT into JavaScript because, perhaps among other things, the object mapper makes heavy use of reflection -- a Java feature not supported in GWT land. – ShabbyDoo Sep 24 '10 at 02:31
  • Ah. Yes, makes sense, thanks for pointing that out (given js-to-java conversions) – StaxMan Sep 24 '10 at 04:59
  • 3
    [gwt-jackson](https://github.com/nmorel/gwt-jackson) "is a GWT JSON serializer/deserializer mechanism based on Jackson annotations" – snorbi Dec 09 '14 at 07:59