Сборка Jacksons ObjectMapper в конкретном случае, когда глобальные настройки настроены - PullRequest
1 голос
/ 04 июля 2019

В моем приложении я настроил Джексона для использования SerializationFeature.WRAP_ROOT_VALUE и DeserializationFeature.UNWRAP_ROOT_VALUE во всем мире.

@Configuration
public class AppConfig {

    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToEnable(SerializationFeature.WRAP_ROOT_VALUE, DeserializationFeature.UNWRAP_ROOT_VALUE);
        return builder;
    }
}

Эта конфигурация работает нормально, но сейчас я нахожусь в ситуации, когда в deserialization случае я получаю ответ JSON без rootname. Итак, у меня есть класс обслуживания, который создает RestTemplate с использованием RestTemplateBuilder и POST некоторых данных для REST-Webservice.

@Service
public class ApiServiceImpl
        implements ApiService<RegisterResponse> {

    private RestTemplate restTemplate;

    public ApiServiceImpl(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder
                .errorHandler(new RestTemplateResponseErrorHandler()).build();
    }

    @Override
    public ResponseEntity<RegisterResponse> callAPI(String requestAsJson,
            String username, String password) {
        ResponseEntity<RegisterResponse> result = null;
        HttpHeaders headers = getHeaders(username, password);

        result = restTemplate.exchange(uri, HttpMethod.POST,
                new HttpEntity<String>(requestAsJson, headers),
                RegisterResponse.class);

        return result;
    }
}

Ответ выглядит следующим образом:

{
    "redirect-url": "https://any-url.com/?with=params"
}

И я хочу десериализовать это непосредственно для следующего POJO. (Как в restTemplate.exchange настроено)

public class RegisterResponse {

    @JsonProperty("redirect-url")
    private String redirectUrl;
    //getter/setter
}

Понятно, что получить это исключение можно из-за функции UNWRAP_ROOT_VALUE:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name 'redirect-url' does not match expected ('RegisterResponse') for type [simple type, class xxx.xxx.xxxservice.xxx.model.response.entity.RegisterResponse]
 at [Source: (String)"{
    "redirect-url": "https://any-url.com/?with=params"
}"; line: 2, column: 5]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1356)
    at com.fasterxml.jackson.databind.ObjectMapper._unwrapAndDeserialize(ObjectMapper.java:4087)

Как я могу настроить Jackson, чтобы не использовать DeserializationFeature.UNWRAP_ROOT_VALUE в данном конкретном случае?

1 Ответ

0 голосов
/ 04 июля 2019

Как прокомментировал Дж. Б. Низет, возможно, установив новый Экземпляр MappingJackson2HttpMessageConverter и ObjectMapper для Джексона в списке MessageConverters.

restTemplate.getMessageConverters().add(getCustomConverter());

private MappingJackson2HttpMessageConverter getCustomConverter() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        MappingJackson2HttpMessageConverter customConverter = 
            new MappingJackson2HttpMessageConverter(mapper);
        if (!restTemplate.getMessageConverters()
                .removeIf(MappingJackson2HttpMessageConverter.class::isInstance)) {
            new RuntimeException("Custom MappingJackson2HttpMessageConverter not found");
        }
        return customConverter;
    }
...