由于公司数据库表的id是利用雪花算法生成的,所以实体类里面定义的数据类型为Long。但是这个数据传到前端时,发生了精度丢失的现象。本文记录了从java后端的角度如何解决这个精度丢失的问题,便于自己后续查阅。

一、问题的描述

    前端通过ajax请求后端接口,返回json数据,然后将数据渲染到一个表格中。突然发现表格中id这一列出现了精度丢失的现象,这精度丢失是由前端引起的。

二、问题的解决

(1)提出方案
    在后端代码中将Long类型改为String类型即可,但是由于采用的SpringMVC框架,可简单的做到统一处理。在输出到页面的Json转换器里面做统一处理,对象序列化成json时,将Long类型变成String类型就可以了。
(2)查询资料
    由于公司里面用的是FastJson的消息转换器,因此我们只需要扩展下FastJsonHttpMessageConverter这个类。
    由于我们需要在fastJson在将对象序列化成Json时做处理,因此先了解下FastJson的SerializeFilter接口。该接口有好多子接口,不同类型的子接口的作用是不同的,具体如下:
SerializeFilter是通过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不同场景的定制序列化。具体如下:

PropertyPreFilter 根据PropertyName判断是否序列化
PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
NameFilter 修改Key,如果需要修改Key,process返回值则可
ValueFilter 修改Value
BeforeFilter 序列化时在最前添加内容
AfterFilter 序列化时在最后添加内容
x
 
1
SerializeFilter是通过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不同场景的定制序列化。具体如下:
2

3
PropertyPreFilter 根据PropertyName判断是否序列化
4
PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
5
NameFilter 修改Key,如果需要修改Key,process返回值则可
6
ValueFilter 修改Value
7
BeforeFilter 序列化时在最前添加内容
8
AfterFilter 序列化时在最后添加内容
(3)实战代码
    • <1>自定义序列化Filter
    由于我们需要在对象序列化成json的阶段,把Long类型的Value变成String类型,因此先写一个ValueFilter的实现类。在这实现类里面,我们把数据类型为Long的数据的Value给修改成String类型。具体代码如下:
package com.kangxiinfo.wechat.common.fastjson;
import com.alibaba.fastjson.serializer.ValueFilter; /**
* Long类型变成String类型——json序列化Filter
* @author ZENG.XIAO.YAN
* @time 2018-11-08 14:50:19
* @version v1.0
*/
public class LongToStringSerializeFilter implements ValueFilter { @Override
public Object process(Object object, String name, Object value) {
if (value != null) {
// 当value不为null时,如果value是Long类型的就改成String
if (value instanceof Long) {
return value.toString();
}
}
return value;
} }
 
1
package com.kangxiinfo.wechat.common.fastjson;
2
import com.alibaba.fastjson.serializer.ValueFilter;
3

4
/**
5
 * Long类型变成String类型——json序列化Filter
6
 * @author ZENG.XIAO.YAN
7
 * @time   2018-11-08 14:50:19
8
 * @version  v1.0
9
 */
10
public class LongToStringSerializeFilter implements ValueFilter {
11

12
    @Override
13
    public Object process(Object object, String name, Object value) {
14
        if (value != null) {
15
            // 当value不为null时,如果value是Long类型的就改成String
16
            if (value instanceof Long) {
17
                return value.toString();
18
            }
19
        }
20
        return value;
21
    }
22
    
23
}

    • <2>自定义JsonHttpMessageConverter
    直接继承FastJsonHttpMessageConverter这个类,然后重写writeInternal这个方法。在writeInternal方法里面进行对象序列成json串时,传入我们上面自定义的序列化Filter。具体代码如下:
package com.kangxiinfo.wechat.common.fastjson;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; public class CustomFastJsonHttpMessageConverter extends FastJsonHttpMessageConverter {
public final static Charset UTF8 = Charset.forName("UTF-8");
private Charset charset = UTF8;
private SerializerFeature[] features = new SerializerFeature[0];
/** 自定义的filter */
private LongToStringSerializeFilter longToStringSerializeFilter = new LongToStringSerializeFilter(); public CustomFastJsonHttpMessageConverter() {
super();
} @Override
protected boolean supports(Class<?> clazz) {
return true;
} public Charset getCharset() {
return this.charset;
} public void setCharset(Charset charset) {
this.charset = charset;
} public SerializerFeature[] getFeatures() {
return features;
} public void setFeatures(SerializerFeature... features) {
this.features = features;
} // 重写这个方法
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
OutputStream out = outputMessage.getBody();
// 转json时 加入自定义的Filter
String text = JSON.toJSONString(obj, longToStringSerializeFilter, features);
byte[] bytes = text.getBytes(charset);
out.write(bytes);
}
}
 
1
package com.kangxiinfo.wechat.common.fastjson;
2
import java.io.IOException;
3
import java.io.OutputStream;
4
import java.nio.charset.Charset;
5
import org.springframework.http.HttpOutputMessage;
6
import org.springframework.http.converter.HttpMessageNotWritableException;
7
import com.alibaba.fastjson.JSON;
8
import com.alibaba.fastjson.serializer.SerializerFeature;
9
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
10

11
public class CustomFastJsonHttpMessageConverter extends FastJsonHttpMessageConverter {
12
    public final static Charset UTF8 = Charset.forName("UTF-8");
13
    private Charset charset = UTF8;
14
    private SerializerFeature[] features = new SerializerFeature[0];
15
    /** 自定义的filter */
16
    private LongToStringSerializeFilter longToStringSerializeFilter = new LongToStringSerializeFilter();
17

18
    public CustomFastJsonHttpMessageConverter() {
19
        super();
20
    }
21

22
    @Override
23
    protected boolean supports(Class<?> clazz) {
24
        return true;
25
    }
26

27
    public Charset getCharset() {
28
        return this.charset;
29
    }
30

31
    public void setCharset(Charset charset) {
32
        this.charset = charset;
33
    }
34

35
    public SerializerFeature[] getFeatures() {
36
        return features;
37
    }
38

39
    public void setFeatures(SerializerFeature... features) {
40
        this.features = features;
41
    }
42

43
    
44
    // 重写这个方法
45
    @Override
46
    protected void writeInternal(Object obj, HttpOutputMessage outputMessage)
47
            throws IOException, HttpMessageNotWritableException {
48
        OutputStream out = outputMessage.getBody();
49
        // 转json时 加入自定义的Filter
50
        String text = JSON.toJSONString(obj, longToStringSerializeFilter, features);
51
        byte[] bytes = text.getBytes(charset);
52
        out.write(bytes);
53
    }
54
}
55

    • <3>在SpringMVC配置文件中配置使用我们自定义的Json转换器
    配置的具体代码如下:
     <mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<!-- 注册我们扩展了的fastjson转换器 -->
<bean class="com.kangxiinfo.wechat.common.fastjson.CustomFastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
</list>
</property>
<property name="features">
<list>
<value>WriteMapNullValue</value>
<value>WriteNullListAsEmpty</value>
<value>WriteNullStringAsEmpty</value>
<value>WriteNullNumberAsZero</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
 
1
     <mvc:annotation-driven>
2
        <mvc:message-converters register-defaults="false">
3
            <!-- 注册我们扩展了的fastjson转换器 -->
4
            <bean class="com.kangxiinfo.wechat.common.fastjson.CustomFastJsonHttpMessageConverter">
5
                <property name="supportedMediaTypes">
6
                    <list>
7
                        <value>text/html;charset=UTF-8</value>
8
                        <value>application/json;charset=UTF-8</value>
9
                        <value>text/plain;charset=UTF-8</value>
10
                        <value>application/x-www-form-urlencoded;charset=UTF-8</value>                        
11
                    </list>
12
                </property>
13
                <property name="features">
14
                    <list>
15
                        <value>WriteMapNullValue</value>
16
                        <value>WriteNullListAsEmpty</value>
17
                        <value>WriteNullStringAsEmpty</value>
18
                        <value>WriteNullNumberAsZero</value>
19
                    </list>
20
                </property>
21
            </bean>
22
        </mvc:message-converters>
23
    </mvc:annotation-driven>

三、小结

(1)Long类型数据传到前端精度丢失时,可以将Long类型转成String类型再输出到前端就不会丢失精度
(2)可以通过扩展SpringMVC的消息转换器,全局处理这种Long类型数据精度丢失的问题

Long类型参数传到前端精度丢失的解决方案的更多相关文章

  1. 后端Long类型传到前端精度丢失的正确解决方式

    原因:前端js对Long类型支持的精度不够,导致后端使用的Long传到前端丢失精度,比如现在分布式id生成算法"雪花算法"在使用中就会出现问题. 解决方式: 1.后端的Long类型 ...

  2. 计算价格, java中浮点数精度丢失的解决方案

    计算价格, java中浮点数精度丢失的解决方案

  3. Spring MVC自定义消息转换器(可解决Long类型数据传入前端精度丢失的问题)

    1.前言 对于Long 类型的数据,如果我们在Controller层通过@ResponseBody将返回数据自动转换成json时,不做任何处理,而直接传给前端的话,在Long长度大于17位时会出现精度 ...

  4. Long类型数据前端精度丢失

    问题描述 后端把Long类型的数据传给前端,前端可能会出现精度丢失的情况.例如:201511200001725439这样一个Long类型的整数,传给前端后会变成201511200001725440 相 ...

  5. .Net Core 配置之long类型 前端精度丢失和时间格式设置

    在很多项目中,都采用的前后端分离的方式进行开发,经常遇到后台的long精度的数据到前端丢失不准确,显示效果为long类型(19位)的后几位为000,此时需要对long的字段进行设置,改变默认的返回类型 ...

  6. springboot中关于Long类型返回前端精度丢失问题处理

    使用了HuTool这个雪花算法后,会出现丢失精度的问题 hutool算法使用地址 对于一些大的业务表,自增主键这里 接口层得注意下是否会产生大数值 设计接口的时候采用String类型. 在项目中,我们 ...

  7. javascript(js)小数精度丢失的解决方案

    原因:js按照2进制来处理小数的加减乘除,在arg1的基础上 将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况. javascript(js)的小数点加减乘除问题,是一个js的bug如0.3* ...

  8. 后端传Long类型至前端js会出现精度丢失问题

    今天开发遇到个问题,Java后端的Long类型数据,传到前端会出现精度丢失,如:164379764419858435,前端会变成164379764419858430.在浏览器中做测试可知,这就是一个精 ...

  9. 后端传给前端Long类型数据,导致精度丢失

    1.前几天遇到了一个问题,后端向前端传递一个Long类型的数据,前端拿到的值不对. 2.当Long类型的数据大于17位时候,就会出现精度丢失的情况. 3.解决办法 我们采用的解决方案是将后端的Long ...

随机推荐

  1. ionic提示弹框

    //提示框 .factory('TipsPort', function ($ionicPopup) { var TipsPort = function (tipsText, SureFunction, ...

  2. 「Android」单例的五种写法

    单例 发现博客园可以很好的设置自己的博客文章的展示,很开心,然后特此发一篇 其实这几种写法大家应该都会的,就权当拿来记录一下吧,以后复习巩固也比较方便. 这篇文章中的代码,来自一篇视频(我想找视频贴上 ...

  3. WPF:Hyperlink如何绑定数据

    <TextBlock> <Hyperlink> <Run Text="{Binding PCFolderPath, Mode=OneWay}"/> ...

  4. mysql之用户管理

    本文内容: 用户的介绍 查看用户 创建用户帐户 修改账户 删除帐户 关于匿名用户 首发日期:2018-04-19 用户的介绍: mysql的客户端连接是以用户名来登录服务端. 服务端可以对用户的权限来 ...

  5. ECS服务器搭建Discuz 邮箱设置,报错处理

    背景 自己想做个网站,没那么多精力,然后就看到了discuz.万网买了一个月的ecs Windows server 2008 r2 服务器,就开始着手安装环境.论坛! 建站 第一次使用discuz论坛 ...

  6. c/c++ 标准库 迭代器(iterator)

    c/c++ 标准库 迭代器 begin和end运算符返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator:如果对象不是常量,返回iteraotor 1 ...

  7. Linux中FTP的一点理解

    FTP(File Transfer Protocol)是一个非常古老并且应用十分广泛的文件传输协议,FTP协议是现今使用最为广泛的网络文件共享协议之一,我们现在也一直有在用着FTP协议来进行各种文件的 ...

  8. 解决git push时发现有超过100M的文件时,删除文件后,发现还是提交不上去的问题

    我这里故意放了一个超过100M的文件 后续,git add ,git commit 然后,git push 此时会发现出现了错误.如果,我们再这里直接在文件系统中删除这个大的文件,然后再次提交,会发现 ...

  9. LeetCode算法题-Maximum Depth of Binary Tree

    这是悦乐书的第164次更新,第166篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第23题(顺位题号是104).给定二叉树,找到它的最大深度.最大深度是从根节点到最远叶节 ...

  10. C语言 矩阵的转置及矩阵的乘法

    C语言 矩阵的转置及矩阵的乘法 //凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1.矩阵的转置 #include<stdio.h> #defi ...