后端统一处理接口返回结果字段为null的json

restful接口返回结果统一处理string类型和数组类型字段

背景

1、在公司多个项目的研发过程中,很多次遇到移动端反馈某个字段或者数组返回了null导致app崩溃或者闪退的情况,最开始只是约定规范大家把string类型或者数组类型的字段都做下初始化操作,防止返回null导致app用到该字段造成应用异常崩溃的情况,后续经过研究可以统一拦截操作,从而分享下方案

2、额外还有在后续对数据库主键使用雪花算法之后long类型返回到前端会存在丢失精度的问题,也是用该方法进行了统一处理,将long类型转为string类型进行返回,防止出现丢失精度的情况

具体代码

1、首先定义json配置类

@Slf4j
public class JacksonAutoConfiguration {
    /**
     * json序列化改造
     * @param builder
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = null;
        try {
            //将Long类型返回时修改为String类型
            builder.serializerByType(Long.class, ToStringSerializer.instance);
            builder.serializerByType(Float.class, FloatSerializer.instance);
            builder.serializerByType(Double.class, DoubleSerializer.instance);
            builder.serializerByType(BigDecimal.class, BigDecimalSerializer.instance);
            //处理Null是否对字符串和数组进行初始化赋值
            objectMapper = builder.createXmlMapper(false).build();
            objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(new MyStringBeanSerializerModifier()));
        } catch (Exception e) {
            log.info("反序列化将所有返回的null值设置为空字符串异常! ");
        }
        return objectMapper;
    }

}

2、下面的代码就是具体要处理哪种类型字段的具体实现,目前项目中只对stirng类型和数组类型做处理,其他大家可以根据自己项目的具体需求进行统一处理,这个拦截最好项目初始化时候使用,中间使用可能会造成部分代码兼容性问题。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @Description: 自定义序列化方法,目前只处理stirng类型和数组类型
 */
public class MyStringBeanSerializerModifier extends BeanSerializerModifier {
    private final JsonSerializer nullStringJsonSerializer = new MyNullStringJsonSerializer();
    private final JsonSerializer nullNumberJsonSerializer = new MyNullNumberJsonSerializer();
    private final JsonSerializer nullArrayJsonSerializer = new MyNullArrayJsonSerializer();
    private final JsonSerializer nullBooleanJsonSerializer = new MyNullBooleanJsonSerializer();
    private final JsonSerializer nullDateJsonSerializer = new MyNullDateJsonSerializer();

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
                                                     List<BeanPropertyWriter> beanProperties) {
        //循环所有的beanPropertyWriter
        for (int i = 0; i < beanProperties.size(); i++) {
            BeanPropertyWriter writer = beanProperties.get(i);
            //判断字段的类型,如果是array,list,set则注册nullSerializer
            if (isStringType(writer)) {
                //给writer注册一个自己的nullSerializer
                writer.assignNullSerializer(this.nullStringJsonSerializer);
            } else if (isArrayType(writer)) {
                //处理数组
                writer.assignNullSerializer(this.nullArrayJsonSerializer);
            }
//            else if(isNumberType(writer)){
//                writer.assignNullSerializer(this.nullNumberJsonSerializer);
//            }else if(isBooType(writer)){
//                writer.assignNullSerializer(this.nullBooleanJsonSerializer);
//            }else if(isDateType(writer)){
//                writer.assignNullSerializer(nullDateJsonSerializer);
//            }
        }
        return beanProperties;
    }

    //判断是什么类型
    private boolean isStringType(BeanPropertyWriter writer) {
        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.equals(String.class);
    }

    //判断是什么类型
    private boolean isLongType(BeanPropertyWriter writer) {
        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.equals(Long.class);
    }

    //判断是什么类型
    private boolean isNumberType(BeanPropertyWriter writer) {

        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.equals(Double.class) || c.equals(Integer.class) || c.equals(Long.class) || c.equals(Short.class) || c.equals(Byte.class) || c.equals(BigDecimal.class);
    }

    //判断是什么类型
    private boolean isArrayType(BeanPropertyWriter writer) {

        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.isArray() || Collection.class.isAssignableFrom(c);
    }

    //判断是什么类型
    private boolean isBooType(BeanPropertyWriter writer) {

        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.equals(boolean.class) || c.equals(Boolean.class);
    }

    //判断是什么类型
    private boolean isDateType(BeanPropertyWriter writer) {

        JavaType clazz = writer.getType();
        Class c = clazz.getRawClass();
        return c.equals(Date.class);
    }
}

class MyNullStringJsonSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        if (value == null) {
            jgen.writeString("");
        } else {
            jgen.writeObject(value);
        }
    }
}

class MyNullArrayJsonSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        if (value == null) {
            jgen.writeStartArray();

            jgen.writeEndArray();
        } else {
            jgen.writeObject(value);
        }
    }
}

class MyNullBooleanJsonSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        if (value == null) {
            jgen.writeBoolean(false);
        } else {
            jgen.writeObject(value);
        }
    }
}

class MyNullDateJsonSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {

        jgen.writeNumber(0);

    }
}

class MyNullNumberJsonSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {

        jgen.writeNumber(0);

    }
}


/**
 * 去除保留空零小数位
 * @author Malcolm
 */
public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {
    public static final BigDecimalSerializer instance = new BigDecimalSerializer();
    @Override
    public void serialize(BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeNumber(value.stripTrailingZeros().toPlainString());
    }
}
public class DoubleSerializer extends JsonSerializer<Double> {
    public static final DoubleSerializer instance = new DoubleSerializer();
    @Override
    public void serialize(Double value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeNumber(new BigDecimal(value).stripTrailingZeros().toPlainString());
    }
}
public class FloatSerializer extends JsonSerializer<Float> {
    public static final FloatSerializer instance = new FloatSerializer();
    @Override
    public void serialize(Float value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeNumber(new BigDecimal(value).stripTrailingZeros().toPlainString());
    }
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值