Sometimes that API you are given just doesn't conform to what you are expecting.

I have had to consume a JSON API recently where the JSON returned "{}" instead of null or not at all.

For example, this is OK:

{
  "name": "Chris",
  "inner": null
}

Ommitting the inner field also OK:

{
  "name": "Chris"
}

But this is plain difficult:

{
  "name": "Chris",
  "inner": {}
}

For what ever reasons I want inner to parse to null.

This will parse empty JSON objects ({}) to null. Hope it helps!

The following snippet will use a new TypeAdapterFactory from GSON 2.2+.

/**
 * Created by Chris on 22/02/15.
 */
public class EmptyCheckTypeAdapterFactory implements TypeAdapterFactory {

    @Override public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
        // We filter out the EmptyCheckTypeAdapter as we need to check this for emptiness!
        if (InnerObject.class.isAssignableFrom(type.getRawType())) {
            final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
            final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
            return new EmptyCheckTypeAdapter<>(delegate, elementAdapter).nullSafe();
        }
        return null;
    }

    public static class EmptyCheckTypeAdapter<T> extends TypeAdapter<T> {

        private final TypeAdapter<T> delegate;
        private final TypeAdapter<JsonElement> elementAdapter;

        public EmptyCheckTypeAdapter(final TypeAdapter<T> delegate, 
                                     final TypeAdapter<JsonElement> elementAdapter) {
            this.delegate = delegate;
            this.elementAdapter = elementAdapter;
        }

        @Override public void write(final JsonWriter out, final T value) throws IOException {
            this.delegate.write(out, value);
        }

        @Override public T read(final JsonReader in) throws IOException {
            final JsonObject asJsonObject = elementAdapter.read(in).getAsJsonObject();
            if (asJsonObject.entrySet().isEmpty()) return null;
            return this.delegate.fromJsonTree(asJsonObject);
        }
    }

}

Then of course add this to your GSON Builder:

new GsonBuilder()  
            .registerTypeAdapterFactory(
                new EmptyCheckTypeAdapterFactory())
            .create();

Reference: http://code.google.com:80/p/google-gson/issues/detail?id=43