Joffrey Joffrey - 1 year ago 147
Java Question

Gson custom deserializer not called for null values

I'm using Gson serialization in a JavaFX context. To avoid having property boilerplate in my serialized Json, I created a handful of custom serializers/deserializers to write the property's value instead of the actual property object, in particular this one for the generic


private static class PropertySerializer implements JsonSerializer<Property<?>> {
public JsonElement serialize(Property<?> property, Type type, JsonSerializationContext context) {
Object value = property.getValue();
return context.serialize(value);

private static class PropertyDeserializer implements JsonDeserializer<Property<?>> {
public Property<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonNull()) {
System.out.println("I am never printed");
Type typeParam = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
Object obj = context.deserialize(json, typeParam);
return new SimpleObjectProperty<>(obj);

It worked pretty well until I stumbled upon null values. By design, when the property's value is null (not the property itself), my serializer will write a null because it writes the value, not the property (I have used
to make it actually write it).

My problem is that, at deserialization time, my custom serializer is not called for null values because of a Gson bug caused by these lines in

@Override public T read(JsonReader in) throws IOException {
if (deserializer == null) {
return delegate().read(in);
JsonElement value = Streams.parse(in);
if (value.isJsonNull()) {
return null; // bypasses my custom deserializer! Why you do dat to me?
return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext);

This results in the property itself being null after deserialization instead of a non-null property containing a null value.

They marked the bug as fixed because apparently there is a workaround using a
, but I can't seem to figure out how to do it. It looks like I have to manually deserialize the object, but I don't know its type so I can't. The
don't provide me with the
of my current
, so I can't rely on its standard deserialization for my value (which I did very easily with the custom deserializer).

private static class PropertyTypeAdapter extends TypeAdapter<Property<?>> {

public void write(JsonWriter out, Property<?> value) throws IOException {
Object valueToSerialize = value.getValue();
// how to use standard serialization of my object?

public Property<?> read(JsonReader in) throws IOException {
switch (in.peek()) {
case NULL:
return new SimpleObjectProperty<>(null);
Type typeOfT = ???
Type typeParam = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
return ???; // how to invoke standard deserialization of my object?

Does anyone know how to solve this?

Answer Source

For future readers: I didn't like the solution I implemented at first in my other answer, so I changed it to use TypeAdapter instead of a custom deserializer.

This takes more code to write, so I ended up writing a lightweight library tailored to use Gson in the context of JavaFX, so that no one has to write it again :)

Here it is: FxGson.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download