Я использую Джексон 2.7.5 с Джерси 2.25.1. Я пытаюсь исправить существующий производственный код, который в настоящее время дает сбой с помощью «UnrecognizedPropertyException: Unrecognized field», когда он получает неожиданное поле во входных данных JSON.
Исследуя это, я обнаружил несколько старых постов (5+ лет), в которых предлагались различные исправления, которые сильно отличались от моего текущего кода. Я не обращал на них особого внимания, потому что они были для старых версий Джексона / Джерси. И более свежие предложения, включая собственную документацию Джерси (https://jersey.github.io/documentation/latest/media.html#json.jackson),, очень похожи на то, что у меня уже есть. На самом деле, на мой взгляд, мой существующий код уже соответствует текущей практике. Однако, Джерси кажется, игнорирует мой пользовательский параметр ObjectMapper ...
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false
Я почти уверен, что настройка должна исправить ошибку, но Джерси, кажется, использует ObjectMapper по умолчанию вместо моих пользовательских настроек.
Во-первых, вот информация о зависимостях, которая, как мне кажется, соответствует тому, что показано в документации на Джерси (https://jersey.github.io/documentation/latest/media.html#json.jackson).
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
Вот вызов, который возвращает ошибку:
// this will throw an exception if it can't convert the string to the class
PropSearchResponse propResponse = null;
try {
propResponse = getResponse.readEntity(PropSearchResponse.class);
} catch(final ProcessingException e) {
throw new ProcessResultException(Code.FAILED, "failed to map from prop response", e);
}
Вот оригинальный код для моего пользовательского ObjectMapper:
@Provider()
@Produces(value = MediaType.APPLICATION_JSON)
public class OutMapperProvider implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public OutMapperProvider() {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"));
}
@Override()
public ObjectMapper getContext(final Class<?> type) {
return mapper;
}
}
Вот пример из документации на Джерси:
@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public MyObjectMapperProvider() {
defaultObjectMapper = createDefaultMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
private static ObjectMapper createDefaultMapper() {
final ObjectMapper result = new ObjectMapper();
result.configure(Feature.INDENT_OUTPUT, true);
return result;
}
}
Я попробовал пример с Джерси (конечно, изменив имена, чтобы соответствовать моим), а также несколько других примеров, которые я нашел в Интернете. Пример Джерси выполняет настройку после @Override. Большинство других примеров делают это до @Override, но все они в значительной степени похожи друг на друга и на мой существующий код. Но, похоже, это не имеет значения. Независимо от того, что я пробовал, пользовательская конфигурация игнорируется, и Джерси вызывает ObjectMapper по умолчанию, который завершается ошибкой в неожиданных полях JSON.
Отказ от ответственности: Это мой первый опыт с Джерси и Джексоном. У меня пока нет хорошего понимания основного механизма. Я просто пытаюсь следовать шаблонам примеров.
Обновление: Я считаю, что приведенный выше код в основном правильный. Но комментарий Павла ниже говорит, что мне нужно зарегистрировать пользовательский ObjectMapper. Я попытался воспроизвести несколько примеров, которые я нашел в Интернете (например, пример 4.2 на https://docs.huihoo.com/jersey/2.13/deployment.html#environmenmt.appmodel,), но безуспешно. Для моей текущей попытки я попытался добавить новый класс MyApplication в существующий пакет конфигурации (com.dmx.repl.config), используя ResourceConfig из Джерси. Код ниже. Но все же, это не работает.
Редактировать: игнорировать этот код, он не работал. Смотрите решение ниже.
package com.dmx.repl.config;
import org.glassfish.jersey.server.ResourceConfig;
import com.dmx.repl.commons.OutMapperProvider;
/**
*
* @author Greg
* @version 1.0
*/
// Attempt to register custom ObjectMapper
public class MyApplication extends ResourceConfig {
public MyApplication() {
// I've tried both of these.
//register(OutMapperProvider.class);
packages("com.dmx.repl.commons");
}
}