java 对象数据映射_SpringMVC中json数据映射为java对象的坑

在开发过程中,我们对外提供的服务可以抽成两大块,一块是不变的,即我们抽象出来的请求头,一块是根据不同的接口而不同的请求体。

packagecom.bijian.study.dto;public class BaseRequest{privateCommonReqHeaderDTO commonReqHeaderDTO;privateT data;publicCommonReqHeaderDTO getCommonReqHeaderDTO() {returncommonReqHeaderDTO;

}public voidsetCommonReqHeaderDTO(CommonReqHeaderDTO commonReqHeaderDTO) {this.commonReqHeaderDTO =commonReqHeaderDTO;

}publicT getData() {returndata;

}public voidsetData(T data) {this.data =data;

}

}

而我们在测试过程发现一个小小的问题,如果对方传的json串都是字符串类型的,则会原封不动地映射到我们的java对象上。但如果对方有传非字符串的值,如25.60,则到映射到对象的值则为25.6,由于我们是面向公网的服务,会对请求过来的数据进行验签,如请求方验签的是25.60,而我们验签的值为成了25.6,则会验签不通过。所以,我特意分析了一下。记录如下:

1.不管是数值还是非数值的的,让请求方统一按字符串传。

2.在我们的系统,每一个请求体都定义一个对象,如这里的BatchOper.java

@ResponseBody

@RequestMapping(value="/addUser", method=RequestMethod.POST)public BaseResponse addUser(HttpServletRequest request, HttpServletResponse response, @RequestBody BaseRequestbaseRequest) {

logger.info("第三方请求,请求参数:{}", JsonUtil.toFullJson(baseRequest));return null;

}

packagecom.bijian.study.dto;importjava.math.BigDecimal;importcom.bijian.study.mapper.CustomBigDecimalSerialize;importcom.bijian.study.mapper.CustomDoubleSerialize;importcom.fasterxml.jackson.databind.annotation.JsonSerialize;public classBatchOper {//批次交易订单号

privateString batchOrderId;//汇总笔数

private inttotalCount;//汇总金额

privateBigDecimal totalAmount;

privateDouble totalAmount2;privateBigDecimal totalAmount3;//文件名称

privateString fileName;publicString getBatchOrderId() {returnbatchOrderId;

}public voidsetBatchOrderId(String batchOrderId) {this.batchOrderId =batchOrderId;

}public intgetTotalCount() {returntotalCount;

}public void setTotalCount(inttotalCount) {this.totalCount =totalCount;

}publicBigDecimal getTotalAmount() {returntotalAmount;

}public voidsetTotalAmount(BigDecimal totalAmount) {this.totalAmount =totalAmount;

}publicDouble getTotalAmount2() {returntotalAmount2;

}public voidsetTotalAmount2(Double totalAmount2) {this.totalAmount2 =totalAmount2;

}publicBigDecimal getTotalAmount3() {returntotalAmount3;

}public voidsetTotalAmount3(BigDecimal totalAmount3) {this.totalAmount3 =totalAmount3;

}publicString getFileName() {returnfileName;

}public voidsetFileName(String fileName) {this.fileName =fileName;

}

}

请求的JSON串如下:

{"commonReqHeaderDTO":{"headReqDate":"20180208","headReqTime":"01241401978"},"data":{"batchOrderId":"0417775230004","totalCount":5,"totalAmount":"252.60","totalAmount2":25.80,"totalAmount3":125.50,"fileName":"/20180417/cs-gdgthzz041702.txt"}}

输出日志如下:

21:13:14.044 INFO com.bijian.study.controller.UserController 67 addUser - 第三方请求,请求参数:{"commonReqHeaderDTO":{"headReqDate":"20180208","headReqTime":"01241401978"},"data":{"batchOrderId":"0417775230004","totalCount":5,"totalAmount":252.60,"totalAmount2":25.8,"totalAmount3":125.50,"fileName":"/20180417/cs-gdgthzz041702.txt"}}

我们不难发现,BigDecimal和String类型的末尾的0还是保留,即正常映射了,但Double类型的则丢掉了最后的0。

因此,方法二就是每一个请求体都定义一个映射对象,数字类型的可以为String,也可以是BigDecimal。

但,对于Double,我们是否还有其它方法呢?这时,我们不难想到SpringMVC的自定义转换器。

packagecom.bijian.study.mapper;importjava.io.IOException;importjava.text.DecimalFormat;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.fasterxml.jackson.databind.SerializerProvider;public class CustomDoubleSerialize extends JsonSerializer{private DecimalFormat df = new DecimalFormat("##.0000");

@Overridepublic voidserialize(Double value, JsonGenerator gen, SerializerProvider serializers)throwsIOException, JsonProcessingException {if(value != null) {//gen.writeString(df.format(value));//转换成字符串

gen.writeNumber(df.format(value));

}

}

}

packagecom.bijian.study.mapper;importjava.io.IOException;importjava.math.BigDecimal;importjava.text.DecimalFormat;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.fasterxml.jackson.databind.SerializerProvider;public class CustomBigDecimalSerialize extends JsonSerializer{private DecimalFormat df = new DecimalFormat("##.000");

@Overridepublic voidserialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers)throwsIOException, JsonProcessingException {if(value != null) {//gen.writeString(df.format(value));

gen.writeNumber(df.format(value));

}

}

}

然后需要给需要转换的属性上面加上注解,如下在totalAmount、totalAmount2分别加上自定义转换器。

packagecom.bijian.study.dto;importjava.math.BigDecimal;importcom.bijian.study.mapper.CustomBigDecimalSerialize;importcom.bijian.study.mapper.CustomDoubleSerialize;importcom.fasterxml.jackson.databind.annotation.JsonSerialize;public classBatchOper {//批次交易订单号

privateString batchOrderId;//汇总笔数

private inttotalCount;//汇总金额

@JsonSerialize(using=CustomBigDecimalSerialize.class)privateBigDecimal totalAmount;

@JsonSerialize(using=CustomDoubleSerialize.class)privateDouble totalAmount2;privateBigDecimal totalAmount3;//文件名称

privateString fileName;publicString getBatchOrderId() {returnbatchOrderId;

}public voidsetBatchOrderId(String batchOrderId) {this.batchOrderId =batchOrderId;

}public intgetTotalCount() {returntotalCount;

}public void setTotalCount(inttotalCount) {this.totalCount =totalCount;

}publicBigDecimal getTotalAmount() {returntotalAmount;

}public voidsetTotalAmount(BigDecimal totalAmount) {this.totalAmount =totalAmount;

}publicDouble getTotalAmount2() {returntotalAmount2;

}public voidsetTotalAmount2(Double totalAmount2) {this.totalAmount2 =totalAmount2;

}publicBigDecimal getTotalAmount3() {returntotalAmount3;

}public voidsetTotalAmount3(BigDecimal totalAmount3) {this.totalAmount3 =totalAmount3;

}publicString getFileName() {returnfileName;

}public voidsetFileName(String fileName) {this.fileName =fileName;

}

}

这时,我们同样用上面的json串请求,输出日志如下:

21:20:28.512 INFO com.bijian.study.controller.UserController 67 addUser - 第三方请求,请求参数:{"commonReqHeaderDTO":{"headReqDate":"20180208","headReqTime":"01241401978"},"data":{"batchOrderId":"0417775230004","totalCount":5,"totalAmount":252.600,"totalAmount2":25.8000,"totalAmount3":125.50,"fileName":"/20180417/cs-gdgthzz041702.txt"}}

但,这种方式在我们的项目中还是不可取,因为不可能把所有请求体都定义出来,这样就达不到我们原来特意做成抽象类的目的了。最后我的方法是在验签前,对JSON串中的有小数点的数字类型的小数做补0处理。方法如下所示:

jsonStr = jsonStr.replaceAll("\\.0,", ".00,");

jsonStr= jsonStr.replaceAll("\\.0}", ".00}");

jsonStr= jsonStr.replaceAll("\\.1,", ".10,");

jsonStr= jsonStr.replaceAll("\\.1}", ".10}");

jsonStr= jsonStr.replaceAll("\\.2,", ".20,");

jsonStr= jsonStr.replaceAll("\\.2}", ".20}");

jsonStr= jsonStr.replaceAll("\\.3,", ".30,");

jsonStr= jsonStr.replaceAll("\\.3}", ".30}");

jsonStr= jsonStr.replaceAll("\\.4,", ".40,");

jsonStr= jsonStr.replaceAll("\\.4}", ".40}");

jsonStr= jsonStr.replaceAll("\\.5,", ".50,");

jsonStr= jsonStr.replaceAll("\\.5}", ".50}");

jsonStr= jsonStr.replaceAll("\\.6,", ".60,");

jsonStr= jsonStr.replaceAll("\\.6}", ".60}");

jsonStr= jsonStr.replaceAll("\\.7,", ".70,");

jsonStr= jsonStr.replaceAll("\\.7}", ".70}");

jsonStr= jsonStr.replaceAll("\\.8,", ".80,");

jsonStr= jsonStr.replaceAll("\\.8}", ".80}");

jsonStr= jsonStr.replaceAll("\\.9,", ".90,");

jsonStr= jsonStr.replaceAll("\\.9}", ".90}");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值