Skip to content
This repository has been archived by the owner on Mar 15, 2022. It is now read-only.
thamtech edited this page Jul 19, 2013 · 2 revisions

JSON related features

<wiki:toc max_depth="3" />

Introduction

JSON (de)serialization works by selecting a "path" expression. In the simplest case the path is just the key of the JSON data. For more complex cases, you can also use a JSONPath expression. If necessary, the selected data is converted to the type of the annotated property.

JSON → POJO

Let's assume you want to map the following JSON data

{
    "isbn": "978-0345417954", 
    "pages": 432,
    "title": "The Hotel New Hampshire",
    "author": {
        "firstname": "John",
        "surname": "Irving", 
    },
    "reviews": [
        "A hectic gaudy saga with the verve of a Marx Brothers movie.", 
        "Rejoice! John Irving has written another book according to your world.", 
        "Spellbinding, intensely human, a high-wire act of dazzling virtuosity."
    ]
}    

Therefore you have the following POJOs in your GWT client

public class Book
{
    String isbn;
    int pages;
    String title;
    Author author;
    List<String> reviews;
}

public class Author
{
    String firstname;
    String surname;
}

To map the JSON to your classes, all you have to do is to define an interface of type !JsonReader<T>:

public class Book
{
    interface BookReader extends JsonReader<Book> {}
    public static final BookReader READER = GWT.create(BookReader.class);

    String isbn;
    int pages;
    String title;
    Author author;
    List<String> reviews;
}

public class Author
{
    interface AuthorReader extends JsonReader<Author> {}
    public static final AuthorReader READER = GWT.create(AuthorReader.class);

    String firstname;
    String surname;
}

Now you can map the JSON by calling

String jsonString = ...; // the above JSON data
Book book = Book.READER.read(jsonString);

Please note that Piriti does not use javascript eval() but the browsers native JSON parser (or a javascript emulation if no native parser is available). Hence the JSON data must confirm to the syntax described at JSON.org. Especially the keys must be enclosed in ". So instead of

{ readonly: true, name: "Foo", createdAt: "08.01.2010", count: 20 }

you have to use

{ "readonly": true, "name": "Foo", "createdAt": "08.01.2010", "count": 20 }

POJO → JSON

POJOs can be serialized to JSON by using the same annotations which are used for parsing. To generate JSON from existings POJO instances you have to define a JsonWriter<T> interface.

public class Book
{
    public interface BookReader extends JsonReader<Book> {}
    public static final BookReader READER = GWT.create(BookReader.class);

    public interface BookWriter extends JsonWriter<Book> {}
    public static final BookWriter WRITER = GWT.create(BookWriter.class);

    String isbn;
    int pages;
    String title;
    Author author;
    List<String> reviews;
}

public class Author
{
    public interface AuthorReader extends JsonReader<Author> {}
    public static final AuthorReader READER = GWT.create(AuthorReader.class);

    public interface AuthorWriter extends JsonWriter<Author> {}
    public static final AuthorWriter WRITER = GWT.create(AuthorWriter.class);

    String firstname;
    String surname;
}

A typical scenario would be to parse the JSON received from the server, make some modifications and send back the modified JSON:

String json = ...; // received from the server
Book book = Book.READER.read(json);
book.title += " 2nd edition";
json = Book.WRITER.toJson(book);
// do some REST request

When POJOs are serialized null values will be processed:

Book book = new Book();
book.isbn = null;
book.pages = 0;
book.title = "";
book.author = null;
book.reviews = new ArrayList<String>();

String json = Book.WRITER.toJson(book); 

will result in

{
    "isbn": null,
    "pages": 0,
    "title": "",
    "author": null,
    "reviews": []
}

JSONPath

By default Piriti uses the fields name as key to the JSON data. But sometimes there's no 1:1 correlation between the field and the JSON key. Say you want to create flat model objects from nested JSON structures:

public class Person
{
    String name;
    String street;
    String city;
}

{
    "name": "Hans Dampf",
    "address": {
        "street": "Hirbeldirbel 1",
        "city": "Equalizerhofen"
    }
}

To map street and city you have to use JSONPath expressions (@ references the current JSONObject):

public class Person
{
    // Reader definition omitted
    String name;
    @Path("@.address.street") String street;
    @Path("@.address.city") String city;
}

Reference

JSONPath is based on the javascript library from Stefan Gössner. See the following links for more examples and the full syntax:

Implementation

When generating the mapping code, Piriti looks at the value of the @Path annotation. In case it detects any of the following characters, the value is interpreted as JSONPath: '$', '@', '.', '[', ']', '*', '#', ',', ':', '?', '(', ')'

Limitations

Please note that fields with JSONPath expressions cannot be serialized. Those fields are skipped by the generated writers:

public class Person
{
    public interface PersonWriter extends JsonWriter<Person> {}
    public static final PersonWriter WRITER = GWT.create(PersonWriter.class);
    
    String name;
    @Path("@.address.street") String street;
    @Path("@.address.city") String city;
}
...
Person p = new Person();
p.name = "Hans Dampf";
p.street = "Hirbeldirbel 1";
p.city = "Equalizerhofen";

String json = Person.WRITER.toJson(p);

will result in

{
    "name": "Hans Dampf"
}
Clone this wiki locally