SpringBoot中Jackson返回null转为空字符串的实现方式

作者:青山常在人不老   阅读 (3367)  |  收藏 (0)  |  点赞 (0)

摘要

SpringBoot返回Json数据中null值处理,将字符串类型null值转换为"",将集合数组类型null值转换为[],将原始数据类型null值转换为0,将布尔类型null值转换为false,将实体对象null值转换为{}。


原文链接:SpringBoot中Jackson返回null转为空字符串的实现方式

Spring boot默认采用jackson进行序列化,通常会出现返回给前端的对象中包含的属性值为null的情况,如果将null返回给前端,前端还需要额外判断返回值是否为null;还有一种方式是将为null的属性不展示给前端,这就造成前端还需要判断属性是否存在,增加前端的工作。

现在提供了一种后端处理返回对象中属性为null的处理方法:

String、Date 为null 则返回"";

Integer、Double、Float为null,返回0;

List、Set为null,返回[];

Map为null,返回{}


若要实现该逻辑,只需要添加一个configuration,在configration中继承jackson序列化对象,然后重写其属性为null时的序列化逻辑即可,代码如下:

package com.example.demo.aop;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.ReflectionUtils;

/**
 * @author 帝眼未来-帮回家
 * 处理响应报文中,属性为Null时的自定义返回值
 *  String、Date:“”
 *  Integer、Double、Float:0
 *  List、Set:[]
 *  Map:{}
 *  Boolean:false
 */
@Slf4j
@Configuration
public class JacksonConfig {
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                JsonStreamContext outputContext = jsonGenerator.getOutputContext();
                //获取到被序列化的对象(包含的所有的属性)
                Object currentValue = outputContext.getCurrentValue();
                //获取当前对象中被序列化的属性
                String currentFeildName = outputContext.getCurrentName();
                //匹配牛逼的首字母大写问题
                currentFeildName = currentFeildName.substring(0,1).toLowerCase()+currentFeildName.substring(1);
                // 一个被序列化的对象找到了,这个当前序列化的属性也找到了,所以如果借用反射方式可以获取当前的类型
                if (currentValue != null) {
                    Field findField = ReflectionUtils.findField(currentValue.getClass(), currentFeildName);
                    if (findField == null) {
                        log.info("当前属性名称:[{}],没有找到对应的实体类中的属性", currentFeildName);
                    }
                    // 获取字段的类型
                    Class<?> filedType = findField.getType(); // 这里开始写入数据
                    //log.info("属性:[{}]的类型为:[{}]" ,currentFeildName, filedType.getName());
                    switch (filedType.getName()) {
                        case "java.lang.String" :
                            jsonGenerator.writeString("");
                            break;
                        case "java.lang.Boolean" :
                            jsonGenerator.writeBoolean(false);
                            break;
                        case "java.lang.Integer" :
                            jsonGenerator.writeNumber(0);
                            break;
                        case "java.lang.Double" :
                        case "java.lang.Float" :
                            jsonGenerator.writeObject(0.0);
                            break;
                        case "java.util.Set" :
                            jsonGenerator.writeObject(new HashSet<>());
                            break;
                        case "java.util.Map" :
                            jsonGenerator.writeObject(new HashMap<>());
                            break;
                        case "java.util.List" :
                            jsonGenerator.writeObject(new ArrayList<>());
                            break;
                        case "java.util.Date" :
                            jsonGenerator.writeObject("");
                            break;
                        default:
                            log.info("当前属性:[{}]的类型:[{}]没匹配逻辑,返回原值", filedType.getName(),currentFeildName);
                            jsonGenerator.writeObject(value);
                    }
                } else {
                    System.out.println("没有匹配到实体类-------" + currentFeildName);
                    jsonGenerator.writeObject(value);
                }
            }
        });
        return objectMapper;
    }
}

测试类如下:

package com.example.demo.entity;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
 * @author 帝眼未来-帮回家
 * 牛逼的jackson能做到让我们惊讶的事情测试类
 */
@Data
public class TestResponse {

    private String name;

    private String fullName;

    @JsonProperty("Addr")
    private String addr;

    private Integer age;

    private List<String> allIds;

    private Map<String,Integer> paramMap;

    private Set<String> paramSet;

    private Boolean isExte;

    private Double aa;

    private Float bbb;

    private Date createDate;

}

controller如下:

package com.example.demo.controller;

import com.example.demo.entity.TestResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author 帝眼未来-帮回家
 * 测试Controller
 */
@Controller
@RequestMapping(value = "/test")
public class TestJsonDefaultController {

    @RequestMapping(value = "/getDealerLicense")
    @ResponseBody
    public TestResponse getDealerLicense(String name,String fullName) {
        TestResponse testResponse = new TestResponse();
        testResponse.setName(name);
        testResponse.setFullName(fullName);
        testResponse.setAddr(null);
        return testResponse;
    }
}

启动服务,访问该链接

http://localhost:8080/test/getDealerLicense?name=%E6%9D%8E%E5%9B%9B

返回结果如下:

{
    "aa": 0,
    "Addr": "",
    "age": 0,
    "allIds": [],
    "bbb": 0,
    "createDate": "",
    "fullName": "",
    "isExte": true,
    "name": "李四",
    "paramMap": {},
    "paramSet": []
}
分类   Spring boot 开发
字数   6142

博客标签    Spring boot null转空字符串  

评论