Jan Seevers
Jan Seevers

Reputation: 788

Use a custom deserializer only on fields?

I do a replication mechanism where I synchronize two databases. For communicating between databases I serialize the objects into JSON using Gson. Each object has a UUID to identify it. To avoid having to send the items that are up to date I use the objects UUID when an object is included in a field in an object to be replicated.

We got the following classes:

public class Entity {
    String uuid;

// Getters and setters..
}

public class Article extends Entity {
    String name;
    Brand brand;

// Getters and setters..
}

public class Brand extens Entity {
    String name;
    Producer producer 

// Getters and setters..
}

public class Producer extends Entity {
    String name;

// Getters and setters..
}

If I serialize Article its JSON representation will look like this:

{"brand":"BrandÖ179d7798-aa63-4dd2-8ff6-885534f99e77","uuid":"5dbce9aa-4129-41b6-a8e5-d3c030279e82","name":"Sun-Maid"}

where "BrandÖ179d7798-aa63-4dd2-8ff6-885534f99e77" is the class ("Brand") and the UUID.

If I serialize Brand I expect:

{"producer":"ProducerÖ173d7798-aa63-4dd2-8ff6-885534f84732","uuid":"5dbce9aa-4129-41b6-a8e5-d3c0302w34w2","name":"Carro"}

In Jackson I would change Article class to:

public class Article {
    String uuid;
String name;
    @JsonDeserialize (using = EntityUUIDDeserializer.class) @ JsonSerialize (using = EntityUUIDSerializer.class)        
    Brand brand;

// Getters and setters..
}

and implement custom serializer and deserializer to return the UUID instead of the object.

Gson do not have a @JsonDeserialize annotation.

If we install the serializer and deserializer doing like this:

Gson gson = new GsonBuilder()
          .registerTypeAdapter(Producer.class, new EntityUUIDDeserializer())
          .registerTypeAdapter(Brand.class, new EntityUUIDDeserializer())  
          .registerTypeAdapter/Producer.class, new EntityUUIDSerializer())
          .registerTypeAdapter(Brand.class, new EntityUUIDSerializer())                 
          .create();

We can serialize Article and Brand ok.

Deserialize Article by

Article article= gson.fromJson(inputJSONString, Article.class);

works fine but

Brand brand= gson.fromJson(inputJSONString, Brand.class);

do not work. I guess the probem is that when we deserialize a Brand we get the deserializer for Brand to kick in trying to return an UUID string, but we want the deserializer to return a Brand-object instead.

Is there a way to avoid creating two different Gson objects? The problem with two diffrent Gson objects is when you want to deserialize an object that contains both Article and Brand.

Upvotes: 3

Views: 6124

Answers (1)

Brian Roach
Brian Roach

Reputation: 76908

You write the serializer/deserializer and register it with Gson (using the GsonBuilder).

https://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserialization

Gson g = new GsonBuilder()
              .registerTypeAdapter(Producer.class, new MyProducerDeserializer())
              .registerTypeAdapter(Producer.class, new MyProducerSerializer())                  
              .create();

When you serialize/deserialize your Brand class, it will use them for the Producer field contained therein.

Upvotes: 1

Related Questions