如何启用“ ALLOW_NUMERIC_LEADING_ZEROS”功能以允许JSON请求正文中的前导零?

时间:2019-04-22 14:26:11

标签: spring jackson jackson2 fasterxml

根据JSON规范,我知道JSON中的整数不允许前导零。但是根据Jackson的文档,Jackson库中有一个属性,即ALLOW_NUMERIC_LEADING_ZEROS,该属性启用后不会在找到前导零时引发异常。

我通过设置以下属性启用了属性ALLOW_NUMERIC_LEADING_ZEROS,但仍然出现错误:Leading zeroes not allowed

spring.jackson.parser.ALLOW_NUMERIC_LEADING_ZEROS=true

相关日志:

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

我通过执行以下代码来验证属性ALLOW_NUMERIC_LEADING_ZEROS是否已启用:

@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'
    */

  ....
}

根据UTF8StreamJsonParser.java中的code,启用此属性后不应发生异常,但是我不确定为什么会发生这种情况! 任何主意是什么原因?

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");
    }

    ...
}

使用的杰克逊图书馆版本:2.9.4

4 个答案:

答案 0 :(得分:0)

这很可能是由于ObjectMapper所配置的Spring端点与注入到字段中的映射器不同。 为什么我不能这么说-也许Spring用户列表可以提供帮助。

答案 1 :(得分:0)

MappingJackson2HttpMessageConverter默认使用Jackson2ObjectMapperBuilder类来构建ObjectMapper类的新实例。要覆盖和使用容器中的ObjectMapper,我们需要覆盖JSON转换器:

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);
    }
}

请参见Customizing HttpMessageConverters with Spring Boot and Spring MVC。从现在开始,您应该能够解析前导零的数字。

答案 2 :(得分:0)

只需将以下属性放在您的application.properties文件中

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

如果未设置默认值,则可以通过以下属性将杰克逊设置为默认转换器

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

答案 3 :(得分:0)

为有此问题并正在寻找更新的工作解决方案的人们提供便条:

  1. 在Maven中导入fasterxml jackson的最新版本(截至今天为2.11.0):

    <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.11.0</version> </dependency>

  2. 创建映射器对象:

    ObjectMapper objectMapper = new ObjectMapper();

  3. 允许数字的前导零(不推荐使用的版本):

    objectMapper.enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature());

二手进口

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.json.JsonReadFeature;

请记住,这将修剪前导0。如果要保留它们,则json值不应为数字。