Заставить Джексона/Гсона во время десериализации генерировать исключение, когда свойство не существует

У меня есть JSON:

{"name": "testname"}

И класс Java с тысячами свойств:

public class Ui {
    public String name;
    public String title;
}

В процессе десериализации Jackson или Gson должны возвращать null или вызывать исключение, поскольку свойство title не существует в данном JSON. Как заставить это поведение?

Пример Джексон:

ObjectMapper objectMapper = new ObjectMapper();
Ui ui = objectMapper.readValue("{\"name": "testname\"}", Ui.class);
System.out.println(ui == null); // should be true

person elron smith    schedule 04.06.2018    source источник


Ответы (2)


Вам нужно создать конструктор, который требует всех необходимых свойств:

class Ui {
    private String name;
    private String title;

    @JsonCreator
    public Ui(@JsonProperty(required = true, value = "name") String name, @JsonProperty(required = true, value = "title") String title) {
        this.name = name;
        this.title = title;
    }
//....
}

И тот же пример дает:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Missing required creator property 'title' (index 1)
 at [Source: {"name": "name"}; line: 1, column: 16]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)

Также взгляните на этот вопрос и ответы: Jackson @JsonProperty(required=true) не выдает исключение

ИЗМЕНИТЬ
Если у вас есть тысячи свойств (что странно, но возможно), простое решение — десериализовать JSON в Map и проверить его размер. Если размер отличается от ожидаемого, вы можете создать новое исключение или вернуть null.

Я думаю, что лучше всего было бы сгенерировать JSON Schema для вашего JSON и попытаться сначала проверить его.

person Michał Ziober    schedule 04.06.2018
comment
Класс пользовательского интерфейса без конструкторов - person elron smith; 05.06.2018
comment
@elronsmith, если вы не можете создать конструктор, вам нужно написать эту проверку вручную или создать JSON Schema. - person Michał Ziober; 05.06.2018

Используя gson, он работает без проблем, он устанавливает только значение для имени.

public class SO_50688866 {

    public static void main(String ... args) {
        String json = "{\"name\": \"testname\"}";

        Ui ui = new Gson().fromJson(json, Ui.class);

        System.out.println(ui.name);
    }

    public static class Ui {
        public String name;
        public String title;
    }
}

ИЗМЕНИТЬ I

Я вижу, вы хотели как раз обратного :)

Я не вижу, чтобы gson поддерживал это изначально, но я нашел этот ответ, который может удовлетворить ваши потребности: Проверка Java в Json с помощью GSON

Также я придумал этот класс, который может выполнять проверку полей после десериализации строки json. У него есть несколько предостережений, например, если отсутствует примитив, например int, он будет инициализирован нулем, поэтому он не будет нулевым. Или, если эффективно, если поля имеют значение null в json. Но, возможно, вы можете адаптировать его для своих нужд, например, добавить метод, который принимает имена полей для проверки.

public static class CheckNullFields<T>{
        @SuppressWarnings("unchecked")
        public void check(T obj) throws IllegalAccessException{
            Class<T> clazz = (Class<T>) obj.getClass();
            Field [] fields = clazz.getDeclaredFields();
            for(Field field : fields) {
                if(field.get(obj) == null) {
                    throw new RuntimeException("Null value in field " + field.getName());
                }
            }
        }
    }

Вы бы использовали это так:

String json = "{\"name\": \"testname\"}";       
try {
    Ui ui = new Gson().fromJson(json, Ui.class);
    new CheckNullFields<Ui>().check(ui);
    System.out.println(ui.name);
    System.out.println(ui.title);
}catch(Exception e) {
    e.printStackTrace();
}            
person Juan    schedule 04.06.2018
comment
Если у json нет параметра заголовка, Gson должен вернуть значение null в Ui. Как это сделать ? - person elron smith; 05.06.2018