Рубрики
Без рубрики

Джексон Исключения – Проблемы и решения

Наиболее распространенные исключения Джексона – причина проблемы и решение для каждого из них.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этом учебнике мы пройдемся по наиболее распространенные Джексон ИсключенияJsonMappingException и НепризнанныйПропертиЭксцепция .

Наконец – мы кратко обсудим Джексон нет таких ошибок метода.

Дальнейшее чтение:

Джексон — пользовательский сериализатор

Контролийте выход JSON с помощью Jackson 2 с помощью пользовательского serializer.
Читать чаще

Джексон Аннотация Примеры

Ядро Джексона в основном набор аннотаций – убедитесь, что вы понимаете это хорошо.
Читать чаще

Начало работы с пользовательской deserialization в Джексон-

Используйте Jackson для карты пользовательского JSON для любого графика Java entity с полным контролем над процессом дезириализации.
Читать чаще

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 основе проекта, поэтому она должна быть легко импортировать и работать, как она есть.