简体   繁体   中英

GSON object serialization breaks when I add a Handler object in my model class

I have a POJO in Android, which is serialized from a server's JSON response with GSON, without any problem.

public ExampleClass implements Serializable {
    @Expose 
    String someProperty;
}

For some reason, I would like to store a Handler object in my class, like:

public ExampleClass implements Serializable {

    private Handler handler = new Handler();

    @Expose 
    String someProperty;
}

After adding this extra line, the serialization breaks with

java.lang.RuntimeException: Failed to invoke public com.example.android.ExampleClass() with no args

I've tried adding a no-args constructor for my class, no success. I've tried making the Handler object transient, but still no success.


UPDATE:

So, I've found the solution. The problem here is that the Handler object is initialized before finishing the serialization of the object.

So this isn't breaking the serialization:

public ExampleClass implements Serializable {

    private Handler handler;

    @Expose 
    String someProperty;
}

But where to initialize it? If I try to do it in the no-args constructor, the serialization breaks again:

public ExampleClass implements Serializable {

    private Handler handler;

    @Expose 
    String someProperty;

    public ExampleClass() {
        handler = new Handler(); // breaks serialization 
    }
}

If I initialize it later when the serialization finished, it works:

public ExampleClass implements Serializable {

    private Handler handler;

    @Expose 
    String someProperty;

    public void functionCalledInTheFuture() {
        handler = new Handler(); // works
    }
}

I am not completely understanding this, so if somebody can explain it to me, please don't hesitate! :)

Well... this is interesting because transient keyword should do the trick. But.. this is only a shortcut to a common use-case. It may not work if the library or code that handle the serialization process ignores it.

There is a good article, that covers serialization topic in JAVA ( read this ). In short : you may customize ExclusionStrategy to add a dedicated behavior to your class

Code highlights:

ExclusionStrategy strategy = new ExclusionStrategy() {
    @Override
    public boolean shouldSkipField(FieldAttributes field) {
        if (field.getDeclaringClass() == MyClass.class && field.getName().equals("other")) {
            return true;
        }
        if (field.getDeclaringClass() == MySubClass.class && field.getName().equals("otherVerboseInfo")) {
            return true;
        }
        return false;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
};

Gson gson = new GsonBuilder()
  .addSerializationExclusionStrategy(strategy)
  .create();
String jsonString = gson.toJson(source);

assertEquals(expectedResult, jsonString);

Yes.. this is probably an overkill to your problem, but it should work for all use cases

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM