根据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
答案 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)
为有此问题并正在寻找更新的工作解决方案的人们提供便条:
在Maven中导入fasterxml jackson的最新版本(截至今天为2.11.0):
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.0</version>
</dependency>
创建映射器对象:
ObjectMapper objectMapper = new ObjectMapper();
允许数字的前导零(不推荐使用的版本):
objectMapper.enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature());
二手进口:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.json.JsonReadFeature;
请记住,这将修剪前导0。如果要保留它们,则json值不应为数字。