Java对象中转换空值的字段

在后端返回数据给前端时,公司的框架会把值为null的数据去掉,方便前端取值。

如:Person对象为:{name:"浩二", age:24, weight:null, height:114},那返回给前端的就为{name:"浩二", age:24, height:114}。

如果这个时候有个需求:

  Integer类型的字段为null给-1

  Long类型的字段为null给-1L

  String类型的字段为null给""(空字符串)

  对象类型的字段为null给new对象,

不能直接动框架,因此需要手动转化。

 

代码写死转换

这种是最简单的方式,顾名思义,写死代码的方式一个一个字段来转换

示例

转换对象 ConvertNullFiledInfo

@Data
public class ConvertNullFiledInfo {
​
    private Integer intNum;
​
    private Long longNum;
​
    private String str;
​
    private ConvertNullFiledInfo info;
​
}

转换代码

@Service
public class ConvertNullFiledService {
​
    /**
     * 写死代码的方式一个一个字段来转换
     * @param info
     * @return
     */
    public ConvertNullFiledInfo convertFunction01(ConvertNullFiledInfo info) {
        info.setIntNum(info.getIntNum() == null ? -1 : info.getIntNum());
        info.setLongNum(info.getLongNum() == null ? -1L : info.getLongNum());
        info.setStr(info.getStr() == null ? "" : info.getStr());
        info.setInfo(info.getInfo() == null ? new ConvertNullFiledInfo() : info.getInfo());
        return info;
    }
    
}

测试代码

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
​
​
@SpringBootTest
@RunWith(SpringRunner.class)
public class ConvertNullFiledServiceTest {
​
    @Autowired
    private ConvertNullFiledService convertNullFiledService;
​
    @Test
    public void convertFunction01() {
        // str和info字段给null
        ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);
        ConvertNullFiledInfo result = convertNullFiledService.convertFunction01(info);
        System.out.println(result);
    }
​
    /**
     * 自定义字段创建ConvertNullFiledInfo
     * @param intNum
     * @param longNum
     * @param str
     * @param info
     * @return
     */
    private ConvertNullFiledInfo createConvertNullFiledInfo(Integer intNum, Long longNum, String str, ConvertNullFiledInfo info) {
        ConvertNullFiledInfo result = new ConvertNullFiledInfo();
        result.setIntNum(intNum);
        result.setLongNum(longNum);
        result.setStr(str);
        result.setInfo(info);
        return result;
    }
    
}

运行结果

可以看到是正常转换了的

问题点

这样写虽然简单方便,但是如果有非常多的对象需要转换,就会有许多重复代码;

而且如果字段有修改(类型、名称、被删除、新增),就需要在去转换方法中修改,因此可以用更好的方式。

 

遍历Filed转换

所有对象都有Class<T>类,而Class有getDeclaredFields()方法,能获取到所有字段(filed),

因此可以使用这种方式来转换。

示例

转换代码

/**
     * 遍历field的方式一个一个字段来转换
     * @param info
     * @return
     */
    public ConvertNullFiledInfo convertByField(ConvertNullFiledInfo info) {
        try {
            Field[] fields = info.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 设置可访问私有变量
                field.setAccessible(true);
                // 获取当前字段值
                Object value = field.get(info);
                // value不为空就跳过
                if (value != null) {
                    continue;
                }
                // 获取当前字段类型
                Class<?> type = field.getType();
                if (type == Integer.class) {
                    // Integer类型就设置为-1
                    field.set(info, -1);
                } else if (type == Long.class) {
                    // Long类型就设置为-1L
                    field.set(info, -1L);
                } else if (type == String.class) {
                    // String类型就设置为“”
                    field.set(info, "");
                } else if (type == ConvertNullFiledInfo.class) {
                    // ConvertNullFiledInfo类型就设置为新对象
                    field.set(info, new ConvertNullFiledInfo());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return info;
    }

测试代码

@Test
public void convertByField() {
    // str和info字段给null
    ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);
    ConvertNullFiledInfo result = convertNullFiledService.convertByField(info);
    System.out.println(result);
}

运行结果

可以看到也是成功转换了

问题点

这种写法仍然存在问题,可以看到方法的传参和返回值都是固定类型为ConvertNullFiledInfo,

并且在遍历field的时候,也有if判断是写定的ConvertNullFiledInfo,

因此也在一定程度上写死了代码

优化

为了避免写死的情况,可以使用泛型来写

转换代码

@Service
public class ConvertNullFiledService<T> {
    
    /**
     * 使用泛型,遍历field的方式一个一个字段来转换
     * @param object
     * @return
     */
    public T convertByFieldGeneric(T object) {
        try {
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 设置可访问私有变量
                field.setAccessible(true);
                // 获取当前字段值
                Object value = field.get(object);
                // value不为空就跳过
                if (value != null) {
                    continue;
                }
                // 获取当前字段类型
                Class<?> type = field.getType();
                if (type == Integer.class) {
                    // Integer类型就设置为-1
                    field.set(object, -1);
                } else if (type == Long.class) {
                    // Long类型就设置为-1L
                    field.set(object, -1L);
                } else if (type == String.class) {
                    // String类型就设置为“”
                    field.set(object, "");
                } else if (type == object.getClass()) {
                    // T类型就设置为新对象
                    Object newObj = object.getClass().newInstance();
                    field.set(object, newObj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
}

测试代码

@Test
public void convertByFieldGeneric() {
    // 全部字段给null
    ConvertNullFiledInfo info = createConvertNullFiledInfo(null, null, null, null);
    ConvertNullFiledInfo result = (ConvertNullFiledInfo) convertNullFiledService.convertByFieldGeneric(info);
    System.out.println(result);
}

运行结果

成功转换

 

热门相关:亿万盛宠只为你   豪门重生盛世闲女   特工重生:快穿全能女神   梦回大明春   朕是红颜祸水