I'm sending 28MB CSV data as Base64 encoded string in json format to REST API. Below is example of request body.
{
"csvData" : "ReallyLargeBase64EncodedString"
}
I get this exception when request is sent to API.
JSON parse error: String value length (20051112) exceeds the maximum allowed (20000000, from `StreamReadConstraints.getMaxStringLength()`); nested exception is com.fasterxml.jackson.databind.JsonMappingException: String value length (20051112) exceeds the maximum allowed (20000000, from `StreamReadConstraints.getMaxStringLength()`)
Jackson core version: 2.16.0
Is it possible to increase default size from 20000000 to custom value?
Jackson's ObjectMapper has an inner factory object with another inner object named StreamReadConstraints, containing a set of parameters; the framework uses a default instance of such object, that is produced in all of Spring's Autoconfigurations; one of these parameters is effectively setting that limit of 20000000 maximum characters that may be exchanged: the name of this parameter is maxStringLength.
Spring's RestClient or RestTemplate, uses Jackson's ObjectMapper, with the added problem that the module also produces its own instance of such object, parallel to the one autoconfigured by the other framework but with the same default parameters.
First of all, you need an ObjectMapper with your own set of custom parameters, to do so you need to setup a bean instancing Jackson2ObjectMapperBuilderCustomizer, as follows:
@Bean
Jackson2ObjectMapperBuilderCustomizer customizer() {
return (builder) -> builder
.postConfigurer(objectMapper -> objectMapper.getFactory()
.setStreamReadConstraints(StreamReadConstraints.defaults()
.rebuild()
.maxStringLength(<<INSERT HERE ANY MAXIMUM VALUE BIGGER THAN 20000000>>)
.build()))
.build();
}
Then you need to inject this customiser wherever you are instancing the ObjectMapper, with your ObjectMapper having to created with the relative builder; there you can apply your customiser on the builder; note that you also need to the default customizer provided by the framework, normally a bean namedstandardJacksonObjectMapperBuilderCustomizer, like this:
@Bean
Jackson2ObjectMapperBuilder customJacksonObjectMapperBuilder(ApplicationContext applicationContext, Jackson2ObjectMapperBuilderCustomizer standardJacksonObjectMapperBuilderCustomizer, Jackson2ObjectMapperBuilderCustomizer customJackson2ObjectMapperBuilderCustomizer) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.applicationContext(applicationContext);
standardJacksonObjectMapperBuilderCustomizer.customize(builder);
customJackson2ObjectMapperBuilderCustomizer.customize(builder); //order matters
return builder;
}
Now, force the adoption of this ObjectMapper in your spring's RestClient, like this:
RestClient.Builder restClientBuilder = RestClient.builder();
builder.messageConverters(c -> {
c.removeIf(MappingJackson2HttpMessageConverter.class::isInstance);
c.add(new MappingJackson2HttpMessageConverter(customObjectMapper));
});
My solution is based on Spring-boot
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With