How to enable 'ALLOW_NUMERIC_LEADING_ZEROS' feature to allow leading zeroes in JSON Request Body?

空扰寡人 提交于 2019-12-24 13:33:09

问题


As per JSON specification, I am aware that leading zeroes are not allowed in integers in JSON. But as per Jackson documentation, there is a property in Jackson library i.e. ALLOW_NUMERIC_LEADING_ZEROS which when enabled, does not throw exceptions when leading zeroes are found.

I enabled the property ALLOW_NUMERIC_LEADING_ZEROS by setting following property and still I am getting error: Leading zeroes not allowed.

spring.jackson.parser.ALLOW_NUMERIC_LEADING_ZEROS=true

Relevant Logs:

Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid numeric value: Leading zeroes not allowed
at [Source: (PushbackInputStream); line: 8, column: 17]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:663) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.base.ParserMinimalBase.reportInvalidNumber(ParserMinimalBase.java:539) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._verifyNoLeadingZeroes(UTF8StreamJsonParser.java:1489) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parsePosNumber(UTF8StreamJsonParser.java:1341) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextFieldName(UTF8StreamJsonParser.java:1025) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:376) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072) ~[jackson-databind-2.9.4.jar:2.9.4]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    ... 63 more

I verified whether the property ALLOW_NUMERIC_LEADING_ZEROS has been enabled or not by executing following code:

@Autowired
private ObjectMapper objectMapper;

@PostMapping(path = "random_path", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> fun123( @RequestBody RandomClass obj) throws Exception {

    log.info(" isEnabled = " + objectMapper.getFactory().isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
    log.info(" isEnabled = " + objectMapper.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));

    /*
        When correct request is given i.e. no leading zeroes in json body , then this function is successfully executed and
        output is true for above two statements  => i.e. feature 'ALLOW_NUMERIC_LEADING_ZEROS' is enabled.

        When leading zeroes are present in json request body, this function is not executed as an exception 'HttpMessageNotReadableException'
        is generated with error message 'Invalid numeric value: Leading zeroes not allowed'
    */

  ....
}

As per code of UTF8StreamJsonParser.java , when this property is enabled the exception should not have occurred, but I am not sure why this is happening !! Any idea what can be the reason behind this ?

Relevant code from UTF8StreamJsonParser.java :

/**
 * Method called when we have seen one zero, and want to ensure
 * it is not followed by another
 */
private final int _verifyNoLeadingZeroes() throws IOException
{
    // Ok to have plain "0"
    if (_inputPtr >= _inputEnd && !_loadMore()) {
        return INT_0;
    }
    int ch = _inputBuffer[_inputPtr] & 0xFF;
    // if not followed by a number (probably '.'); return zero as is, to be included
    if (ch < INT_0 || ch > INT_9) {
        return INT_0;
    }
    // [JACKSON-358]: we may want to allow them, after all...
    if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
        reportInvalidNumber("Leading zeroes not allowed");
    }

    ...
}

Jackson Library Version Used : 2.9.4


回答1:


This is most likely due to ObjectMapper that Spring endpoint uses being configured different from mapper being injected into field. Why this is I can't say -- maybe Spring users list could help.




回答2:


MappingJackson2HttpMessageConverter by default uses Jackson2ObjectMapperBuilder class to build new instance of ObjectMapper class. To override and use ObjectMapper from container we need to override JSON converter:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

@Configuration
public class JacksonMvcConfiguration extends WebMvcConfigurationSupport {

    @Autowired
    private ObjectMapper objectMapper;

    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);

        return converter;
    }

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
        super.configureMessageConverters(converters);
    }
}

See Customizing HttpMessageConverters with Spring Boot and Spring MVC. Since now you should be able to parse numbers with leading zeros.




回答3:


Simply put following property on your application.properties file

spring.jackson.parser.allow-numeric-leading-zeros=true

You can set jackson as default converter by following property if not set default

spring.http.converters.preferred-json-mapper=jackson


来源:https://stackoverflow.com/questions/55795970/how-to-enable-allow-numeric-leading-zeros-feature-to-allow-leading-zeroes-in-j

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!