通过Jackson序列化反序列化解决对象拷贝问题

Posted mada26

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过Jackson序列化反序列化解决对象拷贝问题相关的知识,希望对你有一定的参考价值。

问题背景

最近在项目中遇到一个对象拷贝的问题,无法直接使用BeanUtils.copyProperties(a, b);且使用get set比较麻烦。拷贝涉及到的两个类信息如下:

// 省略get set方法
public class A 

    private int id;

    private String name;

    private List<A> list;

    private Date birthday;

    private LocalDateTime localDateTime;


// 省略get set方法
public class B 

    private int bId;

    private String bName;

    private List<B> bList;

    private Date myBirthday;

    private LocalDateTime localDateTime;


业务场景

  1. 这是一个SpringBoot工程,A是通过feign调用其他服务获取到的,B是本工程的一个Controller接口的返回值
  2. A和B里面的字段其实是一模一样的,B的字段和值来源均为A
    1. 没有直接使用A的原因是:Controller接口的出入参和feign接口的出入参不共用一套,两者解耦开,避免feign接口出入参有修改,controller接口未做调整,前端或其他调controller接口的服务使用出错
    2. 故而B里面的字段可以命名为id(和A保持一致),或者命名为bId(和A 不一致,但值就是A中id的值)
  3. 由于A里面有个List类型的A,即便把B里面的字段完全命名成和A中的字段一样,直接BeanUtils.copyProperties(a, b)也未能成功:B里面的List类型的B值为空
  4. 经分析:可以将A序列化为json,再将json串反序列化为B。
    1. 但是id怎么转换成bId呢,jackson已经提供了此类功能,通过@JsonProperty注解给属性起另一个想要的名称进行转换。
    2. 另外也支持时间类型的字段的转换:通过@JsonFormat注解配置日期格式,可以格式化日期属性。
  5. 进而调整B的代码如下:
// 省略get set方法
public class B 

    // @JsonProperty 在序列号和反序列化时使用,作用于属性上,作用是把该属性的名称序列化成另一个自己想要的名称。
    @JsonProperty("id")
    private int bId;

    @JsonProperty("name")
    private String bName;

    @JsonProperty("list")
    private List<B> bList;

    // @JsonFormat 格式化日期属性
    @JsonProperty("birthday")
    @JsonFormat(pattern = "yyyy年MM月dd日")
    private Date myBirthday;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;


这样就可以通过json序列化、反序列化实现了对象的拷贝List<A>转换成List<B>同理,也可以这样转换。

 @Test
    public void t1() 
        A a = A.builder().id(1).name("name1").list(
                        Arrays.asList(
                                A.builder().id(10).name("name10").list(
                                                Arrays.asList(
                                                        A.builder().id(100).name("name100").list(new ArrayList<>()).build(),
                                                        A.builder().id(101).name("name101").list(new ArrayList<>()).build()
                                                ))
                                        .build(),
                                A.builder().id(11).name("name11").list(new ArrayList<>()).build())
                )
                .birthday(new Date())
                .localDateTime(LocalDateTime.now())
                .build();
        String str = JacksonUtils.writeAsString(a);

        B b = JacksonUtils.readValue(str, B.class);
        System.out.println(JacksonUtils.writeAsString(b));
    

以上是关于通过Jackson序列化反序列化解决对象拷贝问题的主要内容,如果未能解决你的问题,请参考以下文章

通过Jackson序列化反序列化解决对象拷贝问题

jackson对Exception类型对象的序列化与反序列化

Jackson关于Boolean类型反序列化问题

json之jackson序列化反序列化探究(二)

使用Jackson对JSON数组中存放不同对象反序列化

使用Jackson对JSON数组中存放不同对象反序列化