我遇到了一个问题,杰克逊将数值反序列化为我无法预测的任意类型。例如,如果有人传递值“14”,jackson 会将其实例化为
Integer
。然而,如果有人传递值“14.01”,那么 Jackson 会将其实例化为 Double
。这是一个问题,因为我有一个自定义反序列化器(@JsonCreator
),它抛出异常,因为我无法预测将字段转换为 BigDecimal。理想情况下,杰克逊会把一切都变成BigDecimal
。
我发现一篇文章表明杰克逊可能有能力做这样的事情。 在 Jackson 中将 JSON 反序列化为通用映射,强制所有 JSON 浮点为十进制或字符串
但是,我不知道如何访问隐藏在 Spring Boot 中的映射器对象以运行适当的方法
mapper.enable()
。
这是解串器的片段:
@JsonCreator
public OptionTransaction(Map<String,Object> jsonObj){
Map<String,Object> jsonOption = (Map<String, Object>) jsonObj.get("option");
Map<String,Object> optionPriceObj = (Map<String, Object>) jsonOption.get("price");
BigDecimal optionValue = new BigDecimal((Double) optionPriceObj.get("value"));
正如你在上面看到的,
Double
阵容是一个问题,因为杰克逊有时不喂双打。有谁知道一种简单的方法让 Jackson 始终输出 BigDecimals,甚至只是字符串?
更新:
就将双精度数转换为 BigDecimal 而言,我通过按以下方式修改 application.properties 来完成此操作:
# ===============================
# = DESERIALIZATION CUSTOMIZATION
# ===============================
spring.jackson.deserialization.USE_BIG_DECIMAL_FOR_FLOATS=true
@JsonCreator
public OptionTransaction(Map<String,Object> jsonObj){
Map<String,Object> jsonOption = (Map<String, Object>) jsonObj.get("option");
Map<String,Object> optionPriceObj = (Map<String, Object>) jsonOption.get("price");
BigDecimal optionValue = new BigDecimal((Double) optionPriceObj.get("value"));
}
..
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
OptionTransaction transaction = mapper.readValue(jsonString, OptionTransaction.class);
https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.modules(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES), new JavaTimeModule())
.deserializers( new NumberDeserializers.BigDecimalDeserializer())
.featuresToEnable(MapperFeature.AUTO_DETECT_CREATORS)
.build();
}
}
Spring Boot 配置中的设置非常简单:
spring:
jackson:
deserialization:
use-big-decimal-for-floats: true
在 OpenAPI 规范中使用(用于生成 MyClass { BigDecimal id; }:
MyClass:
type: object
properties:
id:
type: number
example: 666.66