我有POJO,就像我有一个BigDecimal字段:
POJO
BigDecimal
public class Foo implements Serializable { private BigDecimal amount; }
我想有BigDecimal的值最多2小数位只。是否存在任何注解,我可以直接在字段级别更改它的值?我也不能改变它的类型。虽然它可以在应用程序中使用getter和ObjectMapper来完成。
2
ObjectMapper
mftmpeh81#
当你想设置比例时,你需要注意四舍五入。你有一些选项,如ROUND_HALF_EVEN,你需要决定使用哪种舍入模式。要拦截BigDecimal的解析,您可以编写自定义解析器。下面的例子展示了如何做到这一点,我们可以扩展默认的一个,并设置规模后,缩放:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; import java.io.File; import java.io.IOException; import java.math.BigDecimal; public class JsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); ObjectMapper mapper = new ObjectMapper(); Foo person = mapper.readValue(jsonFile, Foo.class); System.out.println(person); } } class BigDecimal2JsonDeserializer extends NumberDeserializers.BigDecimalDeserializer { @Override public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { BigDecimal value = super.deserialize(p, ctxt); // set scale value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN); return value; } } class Foo { @JsonDeserialize(using = BigDecimal2JsonDeserializer.class) private BigDecimal amount; public BigDecimal getAmount() { return amount; } public void setAmount(BigDecimal amount) { this.amount = amount; } @Override public String toString() { return "Foo{" + "amount=" + amount + '}'; } }
对于以下JSON有效负载:
JSON
{ "amount": 16.127 }
以上app打印:
Foo{amount=16.13}
mqkwyuun2#
对于你的Kotlin爱好者,我实现了这个BigDeclarationContextualSerializer,其中小数位数可以使用注解配置。虽然在序列化器中引入舍入是一个奇怪的地方,但对我来说这不是问题。检查自己,如果舍入可能是一个问题。Serializer类:
class CustomBigDecimalSerializer(private val decimalPlaces: Int = 2) : StdSerializer<BigDecimal>(BigDecimal::class.java), ContextualSerializer { override fun serialize(value: BigDecimal?, jsonGenerator: JsonGenerator?, serializerProvider: SerializerProvider?) { if (value != null) { jsonGenerator?.writeNumber(value.setScale(decimalPlaces, RoundingMode.HALF_UP)) } else { jsonGenerator?.writeNull() } } override fun createContextual(provider: SerializerProvider?, property: BeanProperty?): JsonSerializer<*> { val decimalPlaces = property?.getAnnotation(DecimalPlaces::class.java) return CustomBigDecimalSerializer(decimalPlaces?.numberOfDigits ?: 2) } }
可用于配置小数位数的注解:
@Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class DecimalPlaces(val numberOfDigits: Int)
最后是它在这个“单元测试”中的用法:
class CustomBigDecimalSerializerTest { @Test fun serializeBigDecimals(){ val objectMapper: ObjectMapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT) val container = BigDecimalContainer(BigDecimal(Math.PI)) // no assertions, just print the serialized container println(objectMapper.writeValueAsString(container)) } data class BigDecimalContainer(val rawValue: BigDecimal){ @JsonSerialize(using = CustomBigDecimalSerializer::class) val defaultDecimalPlaces = rawValue @JsonSerialize(using = CustomBigDecimalSerializer::class) @DecimalPlaces(numberOfDigits = 1) val oneDecimalPlaces = rawValue @JsonSerialize(using = CustomBigDecimalSerializer::class) @DecimalPlaces(numberOfDigits = 2) val twoDecimalPlaces = rawValue @JsonSerialize(using = CustomBigDecimalSerializer::class) @DecimalPlaces(numberOfDigits = 3) val threeDecimalPlaces = rawValue @JsonSerialize(using = CustomBigDecimalSerializer::class) @DecimalPlaces(numberOfDigits = 10) val tenDecimalPlaces = rawValue } }
测试的输出为:
{ "rawValue" : 3.141592653589793115997963468544185161590576171875, "defaultDecimalPlaces" : 3.14, "oneDecimalPlaces" : 3.1, "twoDecimalPlaces" : 3.14, "threeDecimalPlaces" : 3.142, "tenDecimalPlaces" : 3.1415926536 }
玩得开心!
2条答案
按热度按时间mftmpeh81#
当你想设置比例时,你需要注意四舍五入。你有一些选项,如ROUND_HALF_EVEN,你需要决定使用哪种舍入模式。
要拦截
BigDecimal
的解析,您可以编写自定义解析器。下面的例子展示了如何做到这一点,我们可以扩展默认的一个,并设置规模后,缩放:对于以下
JSON
有效负载:以上app打印:
mqkwyuun2#
对于你的Kotlin爱好者,我实现了这个BigDeclarationContextualSerializer,其中小数位数可以使用注解配置。虽然在序列化器中引入舍入是一个奇怪的地方,但对我来说这不是问题。检查自己,如果舍入可能是一个问题。
Serializer类:
可用于配置小数位数的注解:
最后是它在这个“单元测试”中的用法:
测试的输出为:
玩得开心!