2

I have an issue in my Spring projet when I call a web-service that return an object with a attribute that is an empty string.

In my projet I have Spring boot 1.5.2, Spring 4.3.7 and Jackson 2.8.7.

I use a RestTemplate to call web-services.

ResponseEntity<T> responseEntity = restTemplate.exchange("web-service-HttpMethod.GET, null, MyObject.Class);
return responseEntity.getBody();

If I call the web-service in browser, it returns this response :

{
  "display_item_code": "NEP054",
  "historic": false,
  "popin_type_code": "",
  "combo_box": false,
  "max_combo_box_elements": 0,
  "data_max_length": 0,
  "data_precision": 0,
  "data_min_length": 0,
  "data_control_type_code": "",
  "data_control_value1": "",
  "data_control_value2": "",
  "data_format": "MAJUS",
  "translatable": false,
  "translation_key_type_code": "",
  "default_value_setting": "",
  "default_value": "",
  "text_area": false,
  "family_code": "",
  "popin": null,
  "combo_values": null
}

That is the expected result. But when I call this web-service in my application, I obtain this object :

{
  "display_item_code": "NEP054",
  "historic": false,
  "popin_type_code": null,
  "combo_box": false,
  "max_combo_box_elements": 0,
  "data_max_length": 0,
  "data_precision": 0,
  "data_min_length": 0,
  "data_control_type_code": null,
  "data_control_value1": null,
  "data_control_value2": null,
  "data_format": "MAJUS",
  "translatable": false,
  "translation_key_type_code": null,
  "default_value_setting": null,
  "default_value": null,
  "text_area": false,
  "family_code": null,
  "popin": null,
  "combo_values": null
}

All the attributes that have an empty value are now null. I think there is something to configure, maybe an ObjectMapper or a JsonParser, but I don't find what to do. Currently I use the default Serializer, ObjectMapper and JsonParser. I let Spring Boot do the autoconfiguration.

How can I configure my application to keep empty string when it deserialize an object ?

EDIT : I tried this solution by adding a module to the ObjectMapper for string deserialization, but this method is never called.

EDIT 2 : In the BeanDeserializer class, during the deserialization, the JsonToken for the field "popin_type_code" is equal to JsonToken.VALUE_NULL. I don't understand how Spring/Jackson generate this JsonToken.

YLombardi
  • 1,755
  • 5
  • 24
  • 45

2 Answers2

2

I finally found what was my issue.

In my application, I use a custom RestTemplate. But this CustomRestTemplate use the default constructor of the Spring RestTemplate class. So it use the default MessageConverter list.

The solution was to add a constructor for my CustomRestTemplate with the MessageConverter list as input.

@Component
public class CustomRestTemplate extends RestTemplate {
    @Autowired
    public CustomRestTemplate (List<HttpMessageConverter<?>> messageConverters) {
        super(messageConverters);
    }
}

And to configuration the converter with the disabled "ACCEPT_EMPTY_STRING_AS_NULL_OBJECT" feature :

@Configuration
@ComponentScan(basePackages = "com.geodis.rt")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters( List<HttpMessageConverter<?>> converters ) {
        converters.add(0, converter());
    }

    @Bean
    MappingJackson2HttpMessageConverter converter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.getObjectMapper().disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        return converter;
    }

}
YLombardi
  • 1,755
  • 5
  • 24
  • 45
1

Try disabling the ACCEPT_EMPTY_STRING_AS_NULL_OBJECT deserialization feature, but it should not be enabled by default so I would be surprised if this is the solution.

import com.fasterxml.jackson.databind.DeserializationFeature;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();

        builder.featuresToDisable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

        return builder;
    }
}
kagmole
  • 2,005
  • 2
  • 12
  • 27
  • I don't think the default configuration is used so I'm guessing you are thinking in the right direction – Nico Van Belle Jun 16 '17 at 12:27
  • I just tried this solution but it doesn't solve my solve my issue. When the BeanDeserializer deserialize the field "popin_type_code", the JsonToken is equal to JsonToken.VALUE_NULL. – YLombardi Jun 19 '17 at 15:09