【对象属性拷贝】⭐️按照需要转换的类型反射设置拷贝后对象的属性

本文介绍了一种在SpringBoot项目中,如何通过创建封装类并自定义转换方法,处理接口返回值中String类型日期字段转换为Date或LocalDateTime类型,以避免修改原有实体类结构,提高代码安全性和维护性。
摘要由CSDN通过智能技术生成

背景:

        小伙伴们大家好,最近开发的时候遇到一种情况,项目引入了全局序列化器来实现Date,LocalDateTime类型的字段根据时区转换,总体来说接口没什么要改动的,只要原来字段的属性是以上两种就行,但是存在一些String类型的日期字段,该种类型日期字段需要手动改为Date或者LocalDateTime类型

思路:

        指定不能去修改原有的实体类的字段属性,除非你想全局搜索使用挨个更改,所以就将返回封装类复制出一份,单独修改部分属性即可

        因为只用改动String类型的字段,实体类的其他属性直接复制原来的就行,所以直接借助springboot框架中对象拷贝的工具类,然后自定义String类型的日期转换即可

自定义赋值过程源码、如下

        通用的泛型方法,方法需要参数为原始类,以及目标类和指定哪些字段需要单独修改,首先将原始类全部属性深拷贝复制到目标类中,这时字段类型不同的不能赋值成功,所以需要手动添加,通过反射机制获取到原始类的相关字段属性,然后获取到字段的值,进行相应的转换操作. . .

//是一个泛型方法
public static <T> T copyAndConvertDate(Object source, Class<T> target, String... dataTimeFields) {
    //source:源对象,就是要从中复制属性值的对象
    //target:目标类,要创建并接收复制属性的目标类
    //dateTimeFields: 哪些日期字段要处理

        T copiedObject = BeanUtils.instantiateClass(target);
        //创建目标类的实例

        BeanUtils.copyProperties(source, copiedObject);
        //源对象属性值 》》 目标对象

        BeanWrapperImpl beanWrapper = new BeanWrapperImpl(copiedObject);
        //用来操作目标对象的属性

        for (String field : dataTimeFields) {
            try {
                Field declaredField = source.getClass().getDeclaredField(field);
                declaredField.setAccessible(true);
                String fieldValue = (String) declaredField.get(source);
                //反射获取源对象中对应的指定字段,并设置为可以访问(因为是私有属性)

                if (fieldValue != null && fieldValue.matches("\\d{2}-[a-zA-Z]{3}-\\d{4}")) {
                    //这种格式的“23-Jan-2024"的值,走该处理代码
                    Date dateTime = new SimpleDateFormat("dd-MMM-yyyy", Locale.US).parse(fieldValue);
                    //解析为Date对象

                    beanWrapper.setPropertyValue(field, dateTime);
                    //更改目标对象指定字段的属性值

                } else {
                    Date dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(fieldValue);

                    beanWrapper.setPropertyValue(field, dateTime);
                }

            } catch (Exception e) {
                e.printStackTrace();
                log.error("拷贝对象属性:{} -> {} 出错", field, target);
            }
        }
        return copiedObject;
        //返回目标对象
    }

apipost测试下

1、原先的实体类

@Data
public class BlockStructureVO {

    private String issueTime;
    ...//其他属性
}

2、 目标实体类

@Data
public class NewBlockStructureVO {


    private Date issueTime;
    
    ...//其他属性不变
    
}

 3、转换代码块

NewBlockStructureVO newBlockStructureVO = BeanUtil.copyAndConvertDate(blockStructureVO, NewBlockStructureVO.class, "issueTime");
//source: blockStructureVO
//target:  NewBlockStructureVO.class
//指定字段:issueTime

调试一下看看旧的对象和新的对象区别

旧的

新的

对比发现确实只有指定的字段值改变了,别的属性与旧的对象属性相同

章末

        通过这种在接口返回值处理的操作,可以尽量避免修改代码原有结构,知识对原有结果进行了一次封装操作,中间的业务逻辑没有涉及到改动,所以安全性也更高,避免了不必要的测试操作

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

先锋 Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值