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

У меня есть 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

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

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

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)

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

РЕДАКТИРОВАТЬ
Если у вас есть тысячи свойств (что странно, но возможно), простоеРешение - десериализовать JSON до Map и проверить его размер.В случае, если размер отличается от ожидаемого, вы можете выдать новое исключение или вернуть null.

На мой взгляд, лучший способ - это сгенерировать JSON Schema для вашего JSON и попытаться сначала его проверить.

0 голосов
/ 05 июня 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, он будет инициализирован нулем, поэтому он не будет нулевым.Или если эффективно, если поля в 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();
}            
...