Сериализация Gson в зависимости от значения поля

У меня есть POJO, похожий на:

public class MyGsonPojo {

    @Expose
    @SerializedName("value1")
    private String valueOne;

    @Expose
    @SerializedName("value2")
    private boolean valueTwo;

    @Expose
    @SerializedName("value3")
    private int valueThree;

    // Getters and other stuff here
}

Проблема в том, что этот объект должен быть сериализован в тело json для вызова сервера. Некоторые поля являются необязательными для запроса, и если я даже отправлю его со значениями по умолчанию и нулевыми значениями, API ответит по-другому (к сожалению, изменение API не вариант).

Поэтому в основном мне нужно исключить поля из сериализации, если для любого из них установлено значение по умолчанию. Например, если поле valueOne равно null, результирующий json должен быть:

{
    "value2" : true,
    "value3" : 2
}

Любая идея, как сделать это безболезненным усилием? Я бы не хотел создавать тело json вручную.

Любая помощь будет здорово. Спасибо за совет.


person Serj Lotutovici    schedule 06.06.2014    source источник


Ответы (2)


Шаги, которые необходимо выполнить:

  • Преобразуйте строку JSON в Map<String,Object>, используя Gson#fromJson()
  • Повторите карту и удалите запись с карты, которая null
  • Сформируйте строку JSON из окончательной карты, используя Gson#toJson().

Я уже разместил пример кода в том же контексте здесь:

person Braj    schedule 06.06.2014

Вариант 1) Используйте TypeAdapter, см. принятый ответ здесь< /а>:

Вариант 2) При использовании Jackson вместо gson возможно, вы можете аннотировать/сериализовать геттеры вместо полей, и поместите свою логику для возврата всего, что вам нужно для «значений по умолчанию», в ваших геттерах.

//won't get serialized because it's private 
private String valueOne;
...
@JsonSerialize
String getValueOne(){
   if (valueOne == null) return "true"
   else...
}

Вы также можете использовать одну аннотацию @JsonInclude(Include.NON_NULL) или @JsonInclude(Include.NON_EMPTY) в верхней части вашего класса, чтобы предотвратить сериализацию любых нулевых или пустых полей.

person drew moore    schedule 06.06.2014
comment
Спасибо за ваш ответ. К сожалению, Джексон не вариант (для многих объектов для рефакторинга). А TypeAdapter можно исключить, если в объекте 10 или даже 15 полей. - person Serj Lotutovici; 07.06.2014
comment
@SerjLotutovici Что значит можно исключить? - person drew moore; 07.06.2014
comment
Можно исключить как решение. Я не представляю никого, кто попытался бы написать TypeAdapter для объекта с 15 полями — велика вероятность того, что вы сделаете ошибку. Но спасибо за совет Джексона - учту его в моем следующем проекте. - person Serj Lotutovici; 07.06.2014
comment
А, ну да, я бы с вами согласился, если это так. Я бы посмотрел на первое решение @Braj - person drew moore; 07.06.2014