Игнорирование новых полей в объектах JSON с использованием Джексона
Я использую библиотеку Jackson JSON для преобразования некоторых объектов JSON в классы POJO в приложении для Android. Проблема в том, что объекты JSON могут изменяться и иметь новые поля, добавленные во время публикации приложения, но в настоящее время оно будет разрываться даже при добавлении простого поля String, которое можно безопасно игнорировать.
Есть ли способ сказать Джексону, что он игнорирует новые поля? (например, не существует на объектах POJO)? Глобальное игнорирование было бы здорово.
12 ответов
Джексон предоставляет аннотацию, которую можно использовать на уровне класса ( JsonIgnoreProperties).
Добавьте следующее в начало вашего класса (не для отдельных методов):
@JsonIgnoreProperties(ignoreUnknown = true)
public class Foo {
...
}
В зависимости от используемой вами версии Jackson вам придется использовать другой импорт в текущей версии:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
в старых версиях это было:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
В дополнение к двум уже упомянутым механизмам существует также глобальная функция, которая может использоваться для подавления всех сбоев, вызванных неизвестными (не отображенными) свойствами:
// jackson 1.9 and before
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// or jackson 2.0
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Это значение по умолчанию, используемое при отсутствии аннотаций, и может быть удобным откатом.
В курсе и полный ответ с Джексоном 2
Использование аннотации
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyMappingClass {
}
См. JsonIgnoreProperties в онлайн-документации Джексона.
Использование конфигурации
Менее навязчиво, чем аннотация.
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ObjectReader objectReader = objectMapper.reader(MyMappingClass.class);
MyMappingClass myMappingClass = objectReader.readValue(json);
См. FAIL_ON_UNKNOWN_PROPERTIES в онлайн-документации Джексона.
Это может быть достигнуто 2 способами:
Отметьте POJO, чтобы игнорировать неизвестные свойства
@JsonIgnoreProperties(ignoreUnknown = true)
Сконфигурируйте ObjectMapper, который сериализует / десериализует POJO/json, как показано ниже:
ObjectMapper mapper =new ObjectMapper(); // for Jackson version 1.X mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); // for Jackson version 2.X mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
@JsonIgnoreProperties(ignoreUnknown = true)
работал хорошо для меня. У меня есть Java-приложение, которое работает на Tomcat с JDK 1,7.
Если используется класс pojo на основе ответа JSON. Если есть вероятность, что изменения json будут часто объявляться на уровне класса pojo:
@JsonIgnoreProperties(ignoreUnknown = true)
и в objectMapper добавьте это, если вы конвертируете:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Так что этот код не сломается.
Начиная с версии 2.4 и выше, произошли некоторые изменения. Вот как вы это делаете сейчас:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
..........................................................................
ObjectMapper mapper = new ObjectMapper();
// to prevent exception when encountering unknown property:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Примечание: решение на основе @annotation остается тем же самым, поэтому, если вы хотите использовать, смотрите другие ответы.
For more information see the 10 minutes Configuration tutorial at:
https://github.com/FasterXML/jackson-databind
Убедитесь, что вы размещаете @JsonIgnoreProperties(ignoreUnknown = true)
аннотация к родительскому классу POJO, который вы хотите заполнить в результате анализа ответа JSON, а не к классу, где происходит преобразование из JSON в Java Object.
Как указано выше, аннотации работают только в том случае, если это указано в родительском классе POJO, а не в классе, где происходит преобразование из JSON в Java Object.
Другой альтернативой, не затрагивая родительский класс и не вызывая сбоев, является реализация собственной конфигурации mapper только для методов mapper, которые вам необходимы для этого.
Также был перемещен пакет функции десериализации. DeserializationConfig.FAIL_ON_UNKNOWN_PROPERTIES для DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES
import org.codehaus.jackson.map.DeserializationConfig;
...
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Для тех, кто использует Spring Boot, вы можете настроить поведение Джексона по умолчанию, используя Jackson2ObjectMapperBuilder
,
Например:
@Bean
public Jackson2ObjectMapperBuilder configureObjectMapper() {
Jackson2ObjectMapperBuilder oMapper = new Jackson2ObjectMapperBuilder();
oMapper.failOnUnknownProperties(false);
return oMapper;
}
Тогда вы можете автоматически ObjectMapper
везде, где это необходимо (по умолчанию этот объектный преобразователь также будет использоваться для преобразования содержимого http).
Я использую jackson-xxx 2.8.5.Maven Dependency, например:
<dependencies>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
Во-первых, если вы хотите игнорировать неизвестные свойства глобально. Вы можете настроить ObjectMapper
,
Как ниже:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Если вы хотите игнорировать какой-то класс, вы можете добавить аннотацию @JsonIgnoreProperties(ignoreUnknown = true)
на ваш класс, как:
@JsonIgnoreProperties(ignoreUnknown = true)
public class E1 {
private String t1;
public String getT1() {
return t1;
}
public void setT1(String t1) {
this.t1 = t1;
}
}
Вы можете аннотировать конкретное свойство в вашем POJO с помощью @JsonIgnore.