Автор оригинала: Eugen Paraschiv.
1. Обзор
В этом учебнике мы пройдемся по наиболее распространенные Джексон Исключения – JsonMappingException и НепризнанныйПропертиЭксцепция .
Наконец – мы кратко обсудим Джексон нет таких ошибок метода.
Дальнейшее чтение:
Джексон — пользовательский сериализатор
Джексон Аннотация Примеры
Начало работы с пользовательской deserialization в Джексон-
2. “JsonMappingException: Не может построить экземпляр”
2.1. Проблема
Во-первых – давайте посмотрим на Jsonmappingexception: Не может построить экземпляр.
Это исключение брошено, если Джексон не может создать экземпляр класса – это происходит, если класс абстрактные или это просто интерфейс .
В следующем примере мы пытаемся deserialize экземпляр из класса Зоопарк который имеет свойство животных с абстрактные тип Защита :
public class Zoo {
public Animal animal;
public Zoo() { }
}
abstract class Animal {
public String name;
public Animal() { }
}
class Cat extends Animal {
public int lives;
public Cat() { }
}Когда мы пытаемся deserialize JSON Струнные в зоопарк экземпляре он бросает “Jsonmappingexception: Не может построить экземпляр”, как в следующем примере:
@Test(expected = JsonMappingException.class)
public void givenAbstractClass_whenDeserializing_thenException()
throws IOException {
String json = "{"animal":{"name":"lacy"}}";
ObjectMapper mapper = new ObjectMapper();
mapper.reader().forType(Zoo.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of org.baeldung.jackson.exception.Animal,
problem: abstract types either need to be mapped to concrete types,
have custom deserializer,
or be instantiated with additional type information
at
[Source: {"animal":{"name":"lacy"}}; line: 1, column: 2]
(through reference chain: org.baeldung.jackson.exception.Zoo["animal"])
at c.f.j.d.JsonMappingException.from(JsonMappingException.java:148)2.2. Решения
Мы можем решить проблему с помощью простой аннотации – @JsonDeserialize об абстрактном классе:
@JsonDeserialize(as = Cat.class)
abstract class Animal {...}Если у нас есть более чем один подтип абстрактного класса, то мы должны рассмотреть вопрос о том, в том числе подтипа информации, как показано в этой должности: Наследование с Джексоном .
3. JsonMappingException: Нет подходящего конструктора
3.1. Проблема
Теперь – давайте посмотрим на общие Jsonmappingexception: Нет подходящего конструктора найдено для типа .
Это исключение брошено, если Джексон не может получить доступ к конструктору .
В следующем примере – класс Пользователь не имеет конструктора по умолчанию:
public class User {
public int id;
public String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}Когда мы пытаемся deserialize JSON Строка для пользователя Исключение “Jsonmappingexception: Нет подходящий конструктор найден” брошен – как в следующем примере:
@Test(expected = JsonMappingException.class)
public void givenNoDefaultConstructor_whenDeserializing_thenException()
throws IOException {
String json = "{"id":1,"name":"John"}";
ObjectMapper mapper = new ObjectMapper();
mapper.reader().forType(User.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.databind.JsonMappingException:
No suitable constructor found for type
[simple type, class org.baeldung.jackson.exception.User]:
can not instantiate from JSON object (need to add/enable type information?)
at [Source: {"id":1,"name":"John"}; line: 1, column: 2]
at c.f.j.d.JsonMappingException.from(JsonMappingException.java:148)3.2. Решение
Чтобы решить эту проблему – просто добавьте конструктора по умолчанию, как в следующем примере:
public class User {
public int id;
public String name;
public User() {
super();
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
}Теперь, когда мы deserialize – процесс будет работать просто отлично:
@Test
public void givenDefaultConstructor_whenDeserializing_thenCorrect()
throws IOException {
String json = "{"id":1,"name":"John"}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.reader()
.forType(User.class).readValue(json);
assertEquals("John", user.name);
}4. JsonMappingException: Корневое имя не соответствует ожидаемым
4.1. Проблема
Далее – давайте посмотрим на Jsonmappingexception: Корневое имя не соответствует ожидаемым.
Это исключение брошено, если JSON не соответствует именно то, что Джексон ищет ; например, основной JSON может быть обернут, как в следующем примере:
@Test(expected = JsonMappingException.class)
public void givenWrappedJsonString_whenDeserializing_thenException()
throws IOException {
String json = "{"user":{"id":1,"name":"John"}}";
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
mapper.reader().forType(User.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.databind.JsonMappingException:
Root name 'user' does not match expected ('User') for type
[simple type, class org.baeldung.jackson.dtos.User]
at [Source: {"user":{"id":1,"name":"John"}}; line: 1, column: 2]
at c.f.j.d.JsonMappingException.from(JsonMappingException.java:148)
4.2. Решение
Мы можем решить эту проблему с помощью аннотации @JsonRootName – как в следующем примере:
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}Когда мы пытаемся deserialize завернутый JSON – он работает правильно:
@Test
public void
givenWrappedJsonStringAndConfigureClass_whenDeserializing_thenCorrect()
throws IOException {
String json = "{"user":{"id":1,"name":"John"}}";
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
UserWithRoot user = mapper.reader()
.forType(UserWithRoot.class)
.readValue(json);
assertEquals("John", user.name);
}5. JsonMappingException: Серийный игрок не найден для класса
5.1. Проблема
Теперь – давайте посмотрим на Jsonmappingexception: Нет Serializer Найдено для класса.
Это исключение брошено, если вы попытаетесь сериализовать экземпляр, в то время как его свойства и их getters являются частными .
В следующем примере мы пытаемся сериализировать « ПользовательWithPrivateFields “:
public class UserWithPrivateFields {
int id;
String name;
}Когда мы пытаемся сериализировать экземпляр ” ПользовательWithPrivateFields ” – Исключение “Jsonmappingexception: Нет Serializer Найдено для класса” брошен как в следующем примере:
@Test(expected = JsonMappingException.class)
public void givenClassWithPrivateFields_whenSerializing_thenException()
throws IOException {
UserWithPrivateFields user = new UserWithPrivateFields(1, "John");
ObjectMapper mapper = new ObjectMapper();
mapper.writer().writeValueAsString(user);
}Полное исключение:
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.baeldung.jackson.exception.UserWithPrivateFields and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) at c.f.j.d.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
5.2. Решение
Мы можем решить эту проблему, настроили ОбъектМаппер видимость – как в следующем примере:
@Test
public void givenClassWithPrivateFields_whenConfigureSerializing_thenCorrect()
throws IOException {
UserWithPrivateFields user = new UserWithPrivateFields(1, "John");
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
String result = mapper.writer().writeValueAsString(user);
assertThat(result, containsString("John"));
}Или с помощью аннотации @JsonAutoDetect – как в следующем примере:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class UserWithPrivateFields { ... }Конечно, если у нас есть возможность изменить источник класса, мы также можем добавить в getters для Джексона в использовании.
6. JsonMappingException: Не может deserialize Экземпляр
6.1. Проблема
Далее – давайте посмотрим на Jsonmappingexception: Не может deserialize Экземпляр.
Это исключение брошено, если используется неправильный тип в то время как deserializing.
В следующем примере – мы пытаемся deserialize Список Пользователь :
@Test(expected = JsonMappingException.class)
public void givenJsonOfArray_whenDeserializing_thenException()
throws JsonProcessingException, IOException {
String json
= "[{"id":1,"name":"John"},{"id":2,"name":"Adam"}]";
ObjectMapper mapper = new ObjectMapper();
mapper.reader().forType(User.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.databind.JsonMappingException:
Can not deserialize instance of
org.baeldung.jackson.dtos.User out of START_ARRAY token
at [Source: [{"id":1,"name":"John"},{"id":2,"name":"Adam"}]; line: 1, column: 1]
at c.f.j.d.JsonMappingException.from(JsonMappingException.java:148)6.2. Решение
Мы можем решить эту проблему, изменив тип с Пользователь Список
@Test
public void givenJsonOfArray_whenDeserializing_thenCorrect()
throws JsonProcessingException, IOException {
String json
= "[{"id":1,"name":"John"},{"id":2,"name":"Adam"}]";
ObjectMapper mapper = new ObjectMapper();
List users = mapper.reader()
.forType(new TypeReference>() {})
.readValue(json);
assertEquals(2, users.size());
}
7. НепризнаннаяПропертиЭксцепция
7.1. Проблема
Теперь – давайте посмотрим на НепризнанныйПропертиЭксцепция .
Это исключение брошено, если есть неизвестное имущество в Строка в то время как deserializing.
В следующем примере мы пытаемся deserialize JSON String с дополнительным свойством ” проверено “:
@Test(expected = UnrecognizedPropertyException.class)
public void givenJsonStringWithExtra_whenDeserializing_thenException()
throws IOException {
String json = "{"id":1,"name":"John", "checked":true}";
ObjectMapper mapper = new ObjectMapper();
mapper.reader().forType(User.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "checked" (class org.baeldung.jackson.dtos.User),
not marked as ignorable (2 known properties: "id", "name"])
at [Source: {"id":1,"name":"John", "checked":true}; line: 1, column: 38]
(through reference chain: org.baeldung.jackson.dtos.User["checked"])
at c.f.j.d.exc.UnrecognizedPropertyException.from(
UnrecognizedPropertyException.java:51)7.2. Решение
Мы можем решить эту проблему, настроили ОбъектМаппер – как в следующем примере:
@Test
public void givenJsonStringWithExtra_whenConfigureDeserializing_thenCorrect()
throws IOException {
String json = "{"id":1,"name":"John", "checked":true}";
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
User user = mapper.reader().forType(User.class).readValue(json);
assertEquals("John", user.name);
}Или мы можем использовать аннотацию @JsonIgnoreProperties :
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {...}8. JsonParseException: Неожиданный персонаж (“‘ (код 39))
8.1. Проблема
Далее – давайте обсудим JsonParseException: Неожиданный персонаж (“‘ (код 39)) .
Это исключение брошено, если Строка JSON, которая будет deserialized содержит одиночные цитаты вместо двойных котировок.
В следующем примере мы пытаемся deserialize JSON String, содержащий отдельные цитаты:
@Test(expected = JsonParseException.class)
public void givenStringWithSingleQuotes_whenDeserializing_thenException()
throws JsonProcessingException, IOException {
String json = "{'id':1,'name':'John'}";
ObjectMapper mapper = new ObjectMapper();
mapper.reader()
.forType(User.class).readValue(json);
}полное исключение есть:
com.fasterxml.jackson.core.JsonParseException:
Unexpected character (''' (code 39)):
was expecting double-quote to start field name
at [Source: {'id':1,'name':'John'}; line: 1, column: 3]
at c.f.j.core.JsonParser._constructError(JsonParser.java:1419)8.2. Решение
Мы можем решить эту проблему путем настройки ОбъектМаппер чтобы разрешить одиночные котировки:
@Test
public void
givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect()
throws JsonProcessingException, IOException {
String json = "{'id':1,'name':'John'}";
JsonFactory factory = new JsonFactory();
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
ObjectMapper mapper = new ObjectMapper(factory);
User user = mapper.reader().forType(User.class)
.readValue(json);
assertEquals("John", user.name);
}9. Джексон NoSuchMethodError
Наконец – давайте быстро обсудим Джексон “Нет такого метода” ошибки.
Когда java.lang.NoSuchMethodError Исключение брошено, это, как правило, потому, что у вас есть несколько (и несовместимые) версии Джексон банки на вашем classpath.
полное исключение есть:
java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonParser.getValueAsString()Ljava/lang/String; at c.f.j.d.deser.std.StringDeserializer.deserialize(StringDeserializer.java:24)
10. Заключение
В этой статье мы сделали глубокое погружение в наиболее распространенные проблемы Джексона – исключения и ошибки , глядя на потенциальные причины и на решения для каждого из них.
Реализация всех этих примеров и фрагментов кода можно найти на Гитхуб – это Maven основе проекта, поэтому она должна быть легко импортировать и работать, как она есть.