【未解决】自定义Double序列化无法处理null

一、问题出现背景

  • 返回json结果中如果有通过计算获取的double值,小数点后面有很多位小数
{
    "payable": 25.00000000021
}

二、可能原因及尝试过程:

1、原因是double类型计算是不准确的,所以需要处理结果

2、百度找到序列化double的文章使用自定义序列化方法添加json注解解决返回数据double限定小数点后几位长度,多余的舍弃以及double数据控制保留小数的几种方法关于Java中DecimalFormat()方法的调用

  • 添加注解@JsonSerialize
@JsonSerialize(using = Double2Serializer.class)
private Double payable;
  • 自定义序列化对象方法(注意此处JsonSerializer<Object>中的Object是对象类型的泛型,而不能用基本数据类型,编辑器会提示报错的,如double)
public class Double2Serializer extends JsonSerializer<Double> {
    private DecimalFormat df = new DecimalFormat("0.00");

    {
        //显示几位修改几
        df.setMaximumFractionDigits(2);
        df.setGroupingSize(0);
        //默认向上取整,这里直接舍去后面几位
        df.setRoundingMode(RoundingMode.FLOOR);
    }

    @Override
    public void serialize(Double doubleValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (Objects.nonNull(doubleValue)) {
            // 返回出去是字符串
            jsonGenerator.writeString(df.format(doubleValue));
            // 返回出去是数字形式
            //jsonGenerator.writeNumber(df.format(doubleValue));
        } else {
            System.err.println("====== null居然处理了 =====");
            jsonGenerator.writeString(df.format(0.0));
            //jsonGenerator.writeNumber(df.format(0.0));
        }
    }
}
  • 结果是对小数只保留了两位小数,但对null仍然不做处理 
package com.fasterxml.jackson.databind.ser;

@JacksonStdImpl
public class BeanPropertyWriter extends PropertyWriter implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final Object MARKER_FOR_EMPTY;
    protected final SerializedString _name;
    protected final PropertyName _wrapperName;
    protected final JavaType _declaredType;
    protected final JavaType _cfgSerializationType;
    protected JavaType _nonTrivialBaseType;
    protected final transient Annotations _contextAnnotations;
    protected final AnnotatedMember _member;
    protected transient Method _accessorMethod;
    protected transient Field _field;
    protected JsonSerializer<Object> _serializer;
    protected JsonSerializer<Object> _nullSerializer;
    protected TypeSerializer _typeSerializer;
    protected transient PropertySerializerMap _dynamicSerializers;
    protected final boolean _suppressNulls;
    protected final Object _suppressableValue;
    protected final Class<?>[] _includeInViews;
    protected transient HashMap<Object, Object> _internalSettings;

    public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
        Object value = this._accessorMethod == null ? this._field.get(bean) : this._accessorMethod.invoke(bean, (Object[])null);
        // 对null用全局处理,无法继承重写方法
        if (value == null) {
            if (this._nullSerializer != null) {
                gen.writeFieldName(this._name);
                this._nullSerializer.serialize((Object)null, gen, prov);
            }
        } else {
            JsonSerializer<Object> ser = this._serializer;
            if (ser == null) {
                Class<?> cls = value.getClass();
                PropertySerializerMap m = this._dynamicSerializers;
                ser = m.serializerFor(cls);
                if (ser == null) {
                    ser = this._findAndAddDynamic(m, cls, prov);
                }
            }

            if (this._suppressableValue != null) {
                if (MARKER_FOR_EMPTY == this._suppressableValue) {
                    if (ser.isEmpty(prov, value)) {
                        return;
                    }
                } else if (this._suppressableValue.equals(value)) {
                    return;
                }
            }
            // 自定义序列化
            if (value != bean || !this._handleSelfReference(bean, gen, prov, ser)) {
                gen.writeFieldName(this._name);
                if (this._typeSerializer == null) {
                    ser.serialize(value, gen, prov);
                } else {
                    ser.serializeWithType(value, gen, prov, this._typeSerializer);
                }
            }
        }
    }
}
符号位置本地化?含义
0数字阿拉伯数字
#数字

阿拉伯数字

如果不存在就显示为空

.数字小数分隔符或货币小数分隔符
-数字减号
,数字分组分隔符
E数字分割科学技术法中的尾数和指数。在前缀和后缀中无需添加引号
;子模式边界分隔正数和负数子模式
%前缀或后缀乘以100并显示为百分数/u2030前缀或后缀是乘以1000并显示为千分数
¤ (\u00A4)前缀或后缀货币记号,由货币符号替换。如果两个同时出现,则用国际货币符号替换。如果出现在某个模式中,则使用货币小数分隔符,而不使用小数分隔符
'前缀或后缀用于在前缀或或后缀中为特殊字符加引号,例如 "'#'#" 将 123 格式化为 "#123"。要创建单引号本身,请连续使用两个单引号:"# o''clock"
double pi = 3.1415927;//圆周率
//取一位整数
System.out.println(new DecimalFormat("0").format(pi));//3
//取一位整数和两位小数
System.out.println(new DecimalFormat("0.00").format(pi));//3.14
//取两位整数和三位小数,整数不足部分以0填补。
System.out.println(new DecimalFormat("00.000").format(pi));// 03.142
//取所有整数部分
System.out.println(new DecimalFormat("#").format(pi));//3
//以百分比方式计数,并取两位小数
System.out.println(new DecimalFormat("#.##%").format(pi));//314.16%

 /**
  * 上面的代码就是网上很经典的案例,下面我们来分析另外的一个值
  */      
pi=12.34567;
//取一位整数
System.out.println(new DecimalFormat("0").format(pi));//12
//取一位整数和两位小数
System.out.println(new DecimalFormat("0.00").format(pi));//12.35
//取两位整数和三位小数,整数不足部分以0填补。
System.out.println(new DecimalFormat("00.000").format(pi));// 12.346
//取所有整数部分
System.out.println(new DecimalFormat("#").format(pi));//12
//以百分比方式计数,并取两位小数
System.out.println(new DecimalFormat("#.##%").format(pi));//1234.57%

/**
 * 扩展,如果是其他的数字会是下面的效果
 */
pi=12.34;
//整数
System.out.println(new DecimalFormat("6").format(pi));//612
System.out.println(new DecimalFormat("60").format(pi));//612
System.out.println(new DecimalFormat("06").format(pi));//126
System.out.println(new DecimalFormat("00600").format(pi));//00126
System.out.println(new DecimalFormat("#####60000").format(pi));//00126
//小数
System.out.println(new DecimalFormat(".6").format(pi));//12.6
System.out.println(new DecimalFormat(".06").format(pi));//12.36
System.out.println(new DecimalFormat(".60").format(pi));//12.36
System.out.println(new DecimalFormat(".0600").format(pi));//12.3406
System.out.println(new DecimalFormat(".6000").format(pi));//12.3406
System.out.println(new DecimalFormat(".600000##").format(pi));//12.340006

三、最终解决:

  • 使用自定义对象 Double2Serializer 处理 Double 的值,但是对 null 是不做处理的。
  • 对计算结果进行处理,如果为 null 转为0(然后非null会序列化为0.00),或者根据需要不做处理(还是显示null)

备注:

本文主要是借助博客环境,同大家讨论异常问题解决的办法,欢迎大家评论,谢谢!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值