jennymo
jennymo

Reputation: 1480

GSON should ignore class attributes that do not appear in JSON

currently I'm playing with GSON and got into some trouble that I couldn't solve on my own.

I've got these three classes: One abstract class CustomEntity

public abstract class CustomEntity {
     private View customView;

     public CustomEntity() {}

     public void setCustomView(View customView) {
        this.customView = customView;
     }

     public View getCustomView() {
        return customView;
     }
}

Another class LastChange which extends from CustomEntity

public class LastChange extends CustomEntity {

   public Config config;

   public LastChange() {}

   @Override
   public String toString() {
       return "LastChange:" + config.toString();
   }

   public Config getConfig() {
       return config;
   }

   public void setConfig(Config config) {
       this.config = config;
   }
}

And a third class Config

public class Config extends CustomEntity {

   public String config;
   public String nav_items;

   public Config() {}

   @Override
   public String toString() {
       return "config data:" + config + ", " + nav_items;
   }

   public String getConfig() {
       return config;
   }

   public void setConfig(String config) {
       this.config = config;
   }

   public String getNav_items() {
       return nav_items;
   }

   public void setNav_items(String nav_items) {
       this.nav_items = nav_items;
   }
}

In the MainActivity I've tried to deserialize the following JSON into a LastChange object with GSON.

String lastChangeJson = "{\"config\":{\"config\":\"2016-07-20 15:32:14\",\"nav_items\":\"2016-08-24 12:36:06\"},\"background_images\":{\"background_url_landscape\":\"2015-07-28 17:21:56\",\"background_url\":\"2015-07-28 17:21:56\",\"icon_for_accessory_view\":\"2015-07-28 17:21:56\",\"icon_for_route_view\":\"2015-07-28 17:21:56\",\"background_url_landscape_big\":\"2015-07-28 17:21:56\",\"background_url_big\":\"2015-07-28 17:21:56\"},\"nav_content\":[{\"last_change\":\"2016-06-29 11:06:16\",\"pageId\":\"10262\"},{\"last_change\":\"2016-08-24 12:36:06\",\"pageId\":\"10264\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10378\"},{\"last_change\":\"2016-08-09 16:13:03\",\"pageId\":\"10263\"},{\"last_change\":\"2016-07-20 15:32:14\",\"pageId\":\"10265\"}]}";

CustomEntity lastChangeEntity = gson.fromJson(lastChangeJson, LastChange.class);

The code above gives me the following exception:

java.lang.SecurityException: Can't make method constructor accessible
at java.lang.reflect.Constructor.setAccessible(Constructor.java:336)
at com.google.gson.internal.ConstructorConstructor.newDefaultConstructor(ConstructorConstructor.java:101)
at com.google.gson.internal.ConstructorConstructor.get(ConstructorConstructor.java:83)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:99)
at com.google.gson.Gson.getAdapter(Gson.java:423)...

But if I remove the attribute "customView" from the class CustomEntity and its getter and setter, the deserialization works fine.

Anybody got an idea on how I can tell GSON to ignore class attributes, if they don't appear in my json?

Thanks in advance.

Upvotes: 0

Views: 630

Answers (1)

pawelo
pawelo

Reputation: 1415

When building new gson instance:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

Annotate every field you want to serialize with @Expose:

@Expose   
public Config config;

Edit: One small side note - try to avoid keeping references to views (or any Context-related objects) in your models. You may encounter memory leaks if you persist instances of this model in static way and it smells like mixing presentation and data layers, which is never good thing to do for code readability and maintainability.

Upvotes: 1

Related Questions