配置全局设置后,在特殊情况下生成Jacksons ObjectMapper

时间:2019-07-04 06:17:54

标签: java spring spring-boot jackson resttemplate

在我的应用程序中,我将Jackson配置为全局使用SerializationFeature.WRAP_ROOT_VALUEDeserializationFeature.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的情况下,我得到了一个没有rootname的JSON响应。因此,我有一个服务类,该服务类使用RestTemplateRestTemplateBuilder到REST-Webservice的一些数据来构建POST

@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 :(得分:0)

就像JB Nizet所说,可能是通过将Jakson的MappingJackson2HttpMessageConverterObjectMapper的新实例设置为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;
    }