Skip to content

Custom serializers and deserializers

Aleksandar Ivanov edited this page Jul 6, 2017 · 7 revisions

Create a custom (de)serializer

First, create a class that extends com.github.nmorel.gwtjackson.client.JsonSerializer if you want to create a serializer or com.github.nmorel.gwtjackson.client.JsonDeserializer for a deserializer.

public class PersonJsonSerializer extends JsonSerializer<Person> { ... }

The parameter of JsonSerializer and JsonDeserializer is the type you want to (de)serialize.

Then implement your (de)serialization logic in the doSerialize or doDeserialize method.

@Override
public void doSerialize( JsonWriter writer, Person person, JsonSerializationContext ctx, JsonSerializerParameters params ) {
    writer.value( person.getFirstname() + " " + person.getLastname() );
}

In order for the generator to instantiate your (de)serializer, you need a public constructor or, better, a public static method that returns a singleton instance.

private static final PersonSerializer INSTANCE = new PersonSerializer();

/**
 * @return an instance of {@link PersonSerializer}
 */
public static PersonSerializer getInstance() {
    return INSTANCE;
}

private PersonSerializer() { }

The generator first looks for a static method and default to constructor if it can't find one.

In the end, you should have something similar to :

public class PersonSerializer extends JsonSerializer<Person> {

    private static final PersonSerializer INSTANCE = new PersonSerializer();

    /**
     * @return an instance of {@link PersonSerializer}
     */
    public static PersonSerializer getInstance() {
        return INSTANCE;
    }

    private PersonSerializer() { }

    @Override
    protected void doSerialize( JsonWriter writer, Person person, JsonSerializationContext ctx, JsonSerializerParameters params ) {
        writer.value( person.getFirstname() + " " + person.getLastname() );
    }
}

Generic types

If the type you want to (de)serialize is a generic type like Optional, the (de)serializers for the generic's types will be passed to the constructor or static method of your (de)serializer. So you have to add them like OptionalJsonSerializer :

private final JsonSerializer<T> serializer;

/**
 * @param serializer {@link JsonSerializer} used to serialize the object inside the {@link Optional}.
 */
private OptionalJsonSerializer( JsonSerializer<T> serializer ) {
    if ( null == serializer ) {
        throw new IllegalArgumentException( "serializer cannot be null" );
    }
    this.serializer = serializer;
}

For generic Object serialization and deserialization additional parameters need to be provided. For example the full specified class name of the generic object has to be stored.

@JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="class")
public Object object;

Additionally a list of classes that are eligible for generic serialization/deserialization have to be whitelisted in the confuration:

@Override
protected void configure() {
    whitelist("com.package.EligibleClass");
    whitelist("com.package.wildcard.*");//wildcard matching works too
}

Register the custom (de)serializer

To register your (de)serializer, create a class that extends com.github.nmorel.gwtjackson.client.AbstractConfiguration. Then register your class in your *.gwt.xml file with the property gwtjackson.configuration.extension :

<extend-configuration-property name="gwtjackson.configuration.extension" value="com.MyConfiguration" />

Inside the configure() method, you can define serializer and/or deserializer for :

  • primitive types :
primitiveType( boolean.class ).serializer( BooleanJsonSerializer.class ).deserializer( BooleanJsonDeserializer.class );
  • types :
type( String.class ).serializer( StringJsonSerializer.class ).deserializer( StringJsonDeserializer.class );
  • Map's key type :
key( UUID.class ).serializer( UUIDKeySerializer.class ).deserializer( UUIDKeyDeserializer.class );

Examples

You can look at the Guava extension for additional examples :