Настройте Джексона на исключение, если поле отсутствует

У меня есть класс вроде этого:

public class Person {
  private String name;
  public String getName(){
    return name;
  }
}

Я использую ObjectMapper, настроенный следующим образом:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

У меня есть строка str, которая содержит этот { "address" : "something" }. Обратите внимание, что в json нет поля "name". Если я сделаю что-то вроде этого:

mapper.readValue(str, Person.class);

то я действительно верну объект Person с именем, установленным в null. Есть ли способ настроить mapper вместо исключения исключения или вернуть нулевую ссылку вместо Person? Я хочу, чтобы Джексон рассматривал недостающие поля в сбоях и не хотел делать явные проверки нулей в результирующих объектных полях.

Ответ 1

К сожалению, в этот момент Джексон не поддерживается.

Решение может заключаться в добавлении проверки в ваш конструктор. В идеале, если вы не хотите, чтобы эти значения были сериализованы как null, это означает, что вы не должны иметь их как нулевые (построенные другим способом). Например,

public class Person {
  private String name;
  public Person() {
     checkNotNull(name);
  }
} 

однако это может оказаться неудобным во всех ситуациях, особенно если вы используете свой объект, кроме как через сериализацию/десериализацию.

Хотя они имеют атрибут required в аннотации @JsonProperty, он вообще не поддерживается во время десериализации и был введен только для украшения схем JSON. Смотрите тема

Ответ 2

Как и в случае с Jackson 2.6, является способом, но он не работает с аннотациями атрибутов класса, только аннотации конструктора:

/* DOES *NOT* THROW IF bar MISSING */
public class Foo {    
    @JsonProperty(value = "bar", required = true)
    public int bar;
}

/* DOES THROW IF bar MISSING */
public class Foo {
    public int bar;
    @JsonCreator
    public Foo(@JsonProperty(value = "bar", required = true) int bar) {
        this.bar = bar;
    }
}

Ответ 3

У меня была похожая проблема, после десериализации я хотел узнать, все ли в порядке. Этот метод перебирает все поля с помощью JsonProperty Annotation, проверяет, не является ли он нулевым, и смотрит глубже, если этот класс находится в рекурсивном списке (чтобы избежать бесконечных циклов).

private void checkIfFieldsAreNotNull(Object o, List<Class> recursive) {
    Arrays.asList(o.getClass().getDeclaredFields()).stream().filter(field -> field.isAnnotationPresent(JsonProperty.class)).forEach(field -> {
        field.setAccessible(true);
        try {
            assertNotNull(field.get(o));
            if(recursive.contains(field.getType())) {
                checkIfFieldsAreNotNull(field.get(o), recursive);
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    });
}