Как JSON сериализовать нулевые значения, но не пустые значения с Джексоном? - PullRequest
2 голосов
/ 18 апреля 2020

Существует функция Jackson ObjectMapper, которая позволяет удалять пустые значения:

class Car {
   Optional<String> ownerName;
   String manufacturer;

   public Optional<String> getOwnerName() { return ownerName; }
   public String getManufacturer() { return manufacturer; }
}

Car batMobile = new Car();
batMobile.owner = Optional.of("Batman");
batMobile.manufacturer = null;

Car stolenCar = new Car();
stolenCar.owner = Optional.empty();
stolenCar.manufacturer = "Tesla";

ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_ABSENT);

mapper.writeValueAsString(batMobile);
/*
{
  "ownerName": "Batman"
}
*/
mapper.writeValueAsString(stolenCar);
/*
{
  "manufacturer": "Tesla"
}
*/

Вместо этого я хочу, чтобы значения Optional.empty были удалены, но нулевые значения остались:

mapper.writeValueAsString(batMobile);
/*
{
  "ownerName": "Batman",
  "manufacturer": null
}
*/
mapper.writeValueAsString(stolenCar);
/*
{
  "manufacturer": "Tesla"
}
*/

И я хочу, чтобы это применялось глобально, без каких-либо комментариев к DTO.

1 Ответ

1 голос
/ 21 апреля 2020

Если вы используете java.util.Optional, убедитесь, что вы зарегистрировали модуль com.fasterxml.jackson.datatype.jdk8.Jdk8Module, который предоставляет дополнительные сериализаторы и десериализаторы.

В вашем случае самым простым способом было бы использовать аннотацию на уровнях свойств:

class Car {

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    Optional<String> ownerName;

    @JsonInclude
    String manufacturer;

    //getters, setters
}

Значение по умолчанию - Include.ALWAYS, которое следует использовать в вашем случае.

Если вы хотите сделать это глобально, вам нужно внедрить пользовательский фильтр и проверить все случаи вручную. Простой пример:

class CustomFilter {

    @Override
    public boolean equals(Object obj) {
        // return false to keep value in response
        // return true to filter out value from response
        if (obj == null) {
            return false;
        }
        if (obj instanceof Optional) {
            Optional opt = (Optional) obj;
            return !opt.isPresent();
        }
        //other cases if needed

        return false;
    }
}

Вы можете зарегистрировать его, как показано ниже:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.registerModule(new Jdk8Module());
mapper.setDefaultPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.CUSTOM, JsonInclude.Include.CUSTOM, CustomFilter.class, CustomFilter.class));

В случае, если это не то, что вам нужно, вам нужно установить наиболее подходящее значение в глобальном масштабе, и для заданного набора свойств другое значение. Если вы не можете изменить классы DTO, вы всегда можете использовать функцию MixIn.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...