Search code examples
javagson

Gson ignores serialization exclusion strategy


Serializing

public class Subclass extends Superclass {
    private static final long serialVersionUID = 1L;
    private int someProperty;

    public Subclass() {
    }

    public Subclass(int someProperty, String myProperty) {
        super(myProperty);
        this.someProperty = someProperty;
    }

    public int getSomeProperty() {
        return someProperty;
    }

    public void setSomeProperty(int someProperty) {
        this.someProperty = someProperty;
    }
}

with

public class Superclass implements Serializable {
    private static final long serialVersionUID = 1L;
    private String myProperty;

    public Superclass() {
    }

    public Superclass(String myProperty) {
        this.myProperty = myProperty;
    }

    public String getMyProperty() {
        return myProperty;
    }

    public void setMyProperty(String myProperty) {
        this.myProperty = myProperty;
    }
}

shouldn't fail because of

Exception in thread "main" java.lang.IllegalArgumentException: class richtercloud.gson.exclusion.strategy.Subclass declares multiple JSON fields named serialVersionUID
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.Gson.toJson(Gson.java:661)
    at com.google.gson.Gson.toJson(Gson.java:648)
    at com.google.gson.Gson.toJson(Gson.java:603)
    at com.google.gson.Gson.toJson(Gson.java:583)
    at richtercloud.gson.exclusion.strategy.Main.main(Main.java:41)

if a serialization exclusion strategy is used as follows:

Gson gson = new GsonBuilder()
        .excludeFieldsWithModifiers(Modifier.TRANSIENT)
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                boolean retValue = f.getName().equals("serialVersionUID");
                return retValue;
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return false;
            }
        })
        .create();
Subclass a = new Subclass();
String response = gson.toJson(a);
System.out.println(response);

I'm using Gson 2.8.2.


Solution

  • Analysis

    It seems, this is a known issue:

    Some alternative solutions

    Solution #1: Use type adapter

    The recommended solution there (see the «Analysis» links), the workaround, is to introduce an appropriate type adapter.

    Solution #2: Exclude static fields from serialization

    Why not exclude the serialization of the static fields at all?

    new GsonBuilder()
        // ...
        .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC)
        // ...
    

    Solution #3: Serialize @Exposed fields only

    It is possible to explicitly expose serializable fields by using the @Exposed annotation and configure the GsonBuilder appropriately:

    new GsonBuilder()
        // ...
        .excludeFieldsWithoutExposeAnnotation()
        // ...