javascript 精度丢失导致的问题

项目技术:spring boot + mybatis plus+mysql

问题描述:

  使用mybatis plus作数据持久化,id生成机制使用IdWorker(其实就是生成id的雪花算法)。当数据从后台传到前端时该算法生成的id后两位会变为0,

 如1031751585908113410会变为1031751585908113400,究其原因是javascript精度不够不能保存64位长整形的数据导致。

解决方案:

  由于spring boot 默认采用jackson  json 作序列化反序列化器,我们的解决方案就基于jack json

  定义序列化器:

  

public class LongJsonSerializer extends JsonSerializer<Long> {
    @Override
    public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String text = (value == null ? null : String.valueOf(value));
        if (text != null) {
            gen.writeString(text);
        }
    }

}

  定义反序列化器:

public class LongJsonDeserializer extends JsonDeserializer<Long> {
    private static final Logger logger = (Logger) LoggerFactory.getLogger(LongJsonDeserializer.class);
    @Override
    public Long deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {
        String value = jsonParser.getText();
        try {
            return value == null ? null : Long.parseLong(value);
        } catch (NumberFormatException e) {
            logger.error("解析长整形错误", e);
            return null;
        }
    }
}

在bean对象长整形属性上用户注解标注引用序列化器

public class ApiAccount {
    @JsonSerialize(using = LongJsonSerializer.class)
    @JsonDeserialize(using = LongJsonDeserializer.class)
    private Long id;
    @JsonSerialize(using = LongJsonSerializer.class)
    @JsonDeserialize(using = LongJsonDeserializer.class)
    private Long orderId;
    @JsonSerialize(using = LongJsonSerializer.class)
    @JsonDeserialize(using = LongJsonDeserializer.class)
    private Long orgId;

至此,当数据从后端传到前端时长整形会自动转变为字符串,数据从前端传到后端时字符串会自动转变为长整形

另:还有其它方式(通过编写全局转换器,对查询结果中所有的Long都进行转换)尚未研究

posted @ 2018-08-29 10:26  mmhi  阅读(348)  评论(0)    收藏  举报