spring boot - 格式化 金额
场景
业务场景上要对后端返回金额类型字段的数据进行格式化处理,保留两位小数,不足的补0
方案
要求对返回数据格式化,那只能在序列化的下手脚了
CurrencyFormatterSerializer2
所有金额类型返回 string 类型(好像不太完美,但也合理)
public class CurrencyFormatterSerializer2 extends JsonSerializer<Object> {
private static final DecimalFormat FORMAT = new DecimalFormat("0.00");
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
try {
gen.writeString(FORMAT.format(Double.parseDouble(value.toString())));
} catch (NumberFormatException e) {
throw new RuntimeException("异常");
}
}
}
测试:
@NoArgsConstructor
@Data
public class QueryTranDetailResp {
@JsonSerialize(using = CurrencyFormatterSerializer2.class)
private String str;
@JsonSerialize(using = CurrencyFormatterSerializer2.class)
private Double d1;
@JsonSerialize(using = CurrencyFormatterSerializer2.class)
private Float f1;
}
缺点就是 只能格式化一种类型,每次都要重写,还这么长。。
CurrencyFormatterSerializer
目的可以指定格式
1.定义注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@JacksonAnnotationsInside
@JsonSerialize(using = CurrencyFormatterSerializer.class)
public @interface CurrencyFormatter {
/**
* 格式化精度
* @return
*/
String pattern() default "0.00";
/**
* 取整类型
* @return
*/
RoundingMode mode() default RoundingMode.HALF_UP;
}
2.CurrencyFormatterSerializer
@Slf4j
public class CurrencyFormatterSerializer extends JsonSerializer<Object> implements ContextualSerializer {
private String pattern;
private RoundingMode mode;
private static Map<String, CurrencyDecimalFormat> map = new ConcurrentHashMap<>();
/**
* 反序列化默认无参构造函数
*/
public CurrencyFormatterSerializer() {
}
public CurrencyFormatterSerializer(String pattern, RoundingMode mode) {
this.pattern = pattern;
this.mode = mode;
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
//key = pattern.concat(mode.toString())
DecimalFormat FORMAT = map.computeIfAbsent(pattern.concat(mode.toString()), str -> new CurrencyDecimalFormat(new DecimalFormat(pattern), mode)).getFormat();
if (value == null) {
gen.writeNull();
return;
}
if (value instanceof String) {
try {
gen.writeString(FORMAT.format(Float.parseFloat(value.toString())));
} catch (NumberFormatException e) {
e.printStackTrace();
throw new RuntimeException("异常");
}
} else if (value instanceof Double | value instanceof Float | value instanceof Integer | value instanceof BigDecimal) {
log.info("value: {}", FORMAT.format(value));
gen.writeNumber(FORMAT.format(value));
} else {
throw new RuntimeException("异常");
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
if (property != null) {
CurrencyFormatter annotation = property.getAnnotation(CurrencyFormatter.class);
if (annotation == null) {
annotation = property.getContextAnnotation(CurrencyFormatter.class);
}
if (annotation != null) {
return new CurrencyFormatterSerializer(annotation.pattern(), annotation.mode());
}
return prov.findValueSerializer(property.getType(), property);
}
return prov.findNullValueSerializer(property);
}
@Data
class CurrencyDecimalFormat {
private DecimalFormat format;
private RoundingMode mode;
public CurrencyDecimalFormat(DecimalFormat format, RoundingMode mode) {
this.format = format;
this.mode = mode;
format.setRoundingMode(mode);
}
}
}
3.测试
@NoArgsConstructor
@Data
public class QueryTranDetailResp {
@CurrencyFormatter(pattern = "0.000")
private String str;
@CurrencyFormatter
private Double d1;
@CurrencyFormatter(mode = RoundingMode.HALF_DOWN)
private Double d2;
@CurrencyFormatter
private Float f1;
@CurrencyFormatter
private Integer i1;
@CurrencyFormatter
private Integer i2;
@CurrencyFormatter
private BigDecimal b1;
}
@GetMapping("/currency")
public QueryTranDetailResp queryTranDetail() {
QueryTranDetailResp resp = new QueryTranDetailResp();
resp.setStr("100.0184938");
resp.setF1(0.0F);
resp.setD1(200.306D);
resp.setD2(200.301D);
resp.setI1(20);
resp.setB1(new BigDecimal("32.12356"));
return resp;
}
结果:
{
"str": "100.018",
"d1": 200.31, //向上
"d2": 200.30, //向下
"f1": 0.00,
"i1": 20.00,
"i2": null,
"b1": 32.12
}
good luck!