如何解决如何自定义Jackson ObjectMapper在Spring Boot 2.0中允许NaN?
从GitHub移至此处,因为Spring团队仅将GitHub问题用于bug和功能请求。
根据Spring Boot documentation,只要您愿意,就可以使用环境属性(例如,在ObjectMapper
中自定义杰克逊application.properties
,例如spring.jackson.parser.<feature_name>
。没有定义自己的ObjectMapper
bean。
我需要激活ALLOW_NON_NUMERIC_NUMBERS
解析器功能,因为我想使用杰克逊映射到NaN
的浮点字段具有java.lang.Double.NaN
值的JSON(严格来说是无效的) Java。
因此,在我的application.properties
中添加了spring.jackson.parser.ALLOW_NON_NUMERIC_NUMBERS=true
,可以看到它正在被拾取:
- Spring Boot的
JacksonAutoConfiguration
正在创建Jackson2ObjectMapperBuilder
-
Jackson2ObjectMapperBuilder
的{{1}}正在获取我的StandardJackson2ObjectMapperBuilderCustomizer
属性,并将其添加到其spring.jackson.parser.ALLOW_NON_NUMERIC_NUMBERS=true
地图中 -
features
的{{1}}方法最终调用Jackson2ObjectMapperBuilder
,这导致build()
功能(512)的掩码值被添加到configureFeature
ALLOW_NON_NUMERIC_NUMBERS
的{{1}}中的值 - 使用
_parserFeatures
注入到我的bean中的JsonFactory
也启用了ObjectMapper
功能
尚不清楚的是为什么当解析具有浮点字段的ObjectMapper
值的JSON时仍然出现以下Jackson错误:
@Autowired
我正在调试,所以我可能最终会回答自己的问题。上面的详细信息可能是为了帮助来自the GitHub issue的人们找到一个线程,以防万一没有应用他们的功能标志。
解决方法
“问题”是我试图将浮点值映射到Java中的BigDecimal
,但是BigDecimal
没有NaN
(或(-)Inf
的表示)物)。问题起源于com.fasterxml.jackson.databind.util.TokenBuffer.Parser
中的public BigDecimal getDecimalValue()
:
return BigDecimal.valueOf(n.doubleValue());
最终(在java.match.BigDecimal
中)将双精度值转换为字符串"NaN"
,然后将其传递到BigDecimal
构造函数中,构造函数以NumberFormatException
拒绝它以及我在问题中提到的错误消息:
throw new NumberFormatException("Character " + c
+ " is neither a decimal digit number,decimal point,nor"
+ " \"e\" notation exponential mark.");
就我而言,我很高兴将NaN
映射到null
,但是我知道这并不是每个使用Jackson的人的正确行为,因此我编写了一个自定义解串器来完成
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
import java.io.IOException;
import java.math.BigDecimal;
public class NaNSafeBigDecimalDeserializer extends JsonDeserializer<BigDecimal> {
private BigDecimal nanValue = null;
@Override
public BigDecimal deserialize(JsonParser p,DeserializationContext ctxt) throws IOException,JsonProcessingException {
if (p.isNaN()) {
return nanValue;
} else {
return NumberDeserializers.BigDecimalDeserializer.instance.deserialize(p,ctxt);
}
}
}
现在我可以用BigDecimal
注释我的@JsonDeserialize(using = NaNSafeBigDecimalDeserializer.class)
字段。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。