Ошибочная сериализация полей с Gson

240
13 октября 2017, 13:41

У меня в обьекте есть поле:

@SerializedName("CommentPhotoes")
@Expose(serialize = false)
private ArrayList<CommentPhoto> commentPhotos;

Мне это поле нужно распарсить когда я считываю этот объект из строки, но когда я его обратно сериализую в строку, это поле не должно туда попасть.

Проблема заключается в том что при сериализации объекта - это поле тоже сериализуется. При чем тоже самое касается и десериализации.

В чем может быть проблема, может я неправильно использую эти аннотации?

Answer 1

По умолчанию наличие аннотации @Expose ни на что не влияет. Поэтому при создании объекта Gson с помощью GsonBuilder нужно явно указать, как обрабатывать эти аннотации.

Возможны варианты:

  1. Помечать нужные поля этой аннотацией
  2. Помечать игнорируемые поля этой аннотацией
  3. Использовать модификатор transient вместо аннотаций

Подробнее:

  1. Помечаем поля, которые хотим сериализовать/десериализовать аннотацией @Expose, при создании Gson объекта говорим, что поля без этой аннотации надо игнорировать:

    Gson gson = new GsonBuilder()
        .excludeFieldsWithoutExposeAnnotation()
        .create();
    
  2. Помечаем поля, которые хотим игнорировать и в сериализации и в десериализации аннотацией @Expose, при создании Gson объекта добавляем ExclusionStrategies:

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return f.getAnnotation(Exclude.class) != null;
            }
            @Override
            public boolean shouldSkipClass(Class<?> c) {
                return false;
            }
        })
        .create();
    

    Чтобы исключить поля только в сериализации или только в десериализации нужно добавлять аннотацию @Expose с параметром serialize=false или deserialize=false:

    class Book {
        // игнорируется только при сериализации
        @Expose(serialize = false) String field1;
        // игнорируется только при десериализации
        @Expose(deserialize = false) String field2;
    }
    

    и при создании Gson объекта настроить правильное исключение полей с этими аннотациями:

    new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                Expose expose = f.getAnnotation(Expose.class);
                return expose != null && !expose.serialize();
            }
            @Override
            public boolean shouldSkipClass(Class<?> c) {
                return false;
            }
        })
        .addDeserializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                Expose expose = f.getAnnotation(Expose.class);
                return expose != null && !expose.deserialize();
            }
            @Override
            public boolean shouldSkipClass(Class<?> c) {
                return false;
            }
        })
        .create();
    
  3. Также чтобы исключить поле можно добавить к нему модификатор transient:

    class Book {
        transient String name;
    }
    
Answer 2

Возможно вы не настроили экземпляр Gson. Попробуйте так:

new GsonBuilder()
    .addSerializationExclusionStrategy(new ExclusionStrategy() {
        @Override
        public boolean shouldSkipField(FieldAttributes fieldAttributes) {
            final Expose expose = fieldAttributes.getAnnotation(Expose.class);
            return expose != null && !expose.serialize();
        }
        @Override
        public boolean shouldSkipClass(Class<?> aClass) {
            return false;
        }
    })
    .addDeserializationExclusionStrategy(new ExclusionStrategy() {
        @Override
        public boolean shouldSkipField(FieldAttributes fieldAttributes) {
            final Expose expose = fieldAttributes.getAnnotation(Expose.class);
            return expose != null && !expose.deserialize();
        }
        @Override
        public boolean shouldSkipClass(Class<?> aClass) {
            return false;
        }
    })
    .create();
READ ALSO
Вопрос по защите приложения

Вопрос по защите приложения

Вообще никак нельзя определить, что приложение декомпилируетсяДекомпилятор работает с кодом как с потоком байтов, а не исполняемой сущностью

280
В чём разница между İnterface и Abstract класс

В чём разница между İnterface и Abstract класс

Добрый деньРаньше interface не имеел реализации и нам приходилось реализовывать абстрактные классы тд и тп

222