当前位置: 首页 > 科技观察

一些简化JavaBeans定义和转换的小技巧

时间:2023-03-19 00:57:35 科技观察

今天在封装第三方应用的开放接口,写了很多有返回值的类。其中许多类具有相似的结构,但各个字段的名称不同。对于一个单独的字段,复制和更改很麻烦,命名是最麻烦的事情。就像下面两个:@EqualsAndHashCode(callSuper=true)@DatapublicclassSimpleUserResponseextendsWeComResponse{privateListuserlist;}@EqualsAndHashCode(callSuper=true)@DatapublicclassUserDetailResponseextendsWeComResponse{privateListuserlist;}是不是很像?所以使用泛型将它们合并:@EqualsAndHashCode(callSuper=true)@DatapublicclassUserResponseextendsWeComResponse{privateListuserlist;}这样,它们就可以通过UserResponse和UserResponse来定义,简化了很多代码。但是没过多久又来了一个类:@EqualsAndHashCode(callSuper=true)@DatapublicclassQrCodeResponseextendsWeComResponse{privateStringqrcode;}这个结构其实是差不多的。如果UserResponse进一步转化为:@EqualsAndHashCode(callSuper=true)@DatapublicclassOjbectResponseextendsWeComResponse{privateTuserlist;}看来OjbectResponse等同于QrCodeResponse。但仅仅这样做是不够的。细心的同学会发现他们的属性名不一样,一个是qrcode;另一个是用户列表。有别名就好了!我似乎有解决办法。如果是类型转换Bean类型转换,Mapstruct可以解决这个问题,最后我们将属性名定义为data:@Mapping(target="data",source="qrcode")@Mapping(target="data",source="userlist")就是通过上面两个注解映射写两个转换接口来解决的。关于Mapstruct,可以看我的相关讲解文章。如果反序列化Jackson提供别名注解@JsonAlias,字段属性名可以接受更多的别名。像这样:@EqualsAndHashCode(callSuper=true)@DatapublicclassOjbectResponseextendsWeComResponse{@JsonAlias({"qrcode","userlist"})privateTdata;}然后下面的json可以映射到OjbectResponse:{"qrcode":"https://felord.cn/myqr.png"}这个会映射到OjbectResponse{"userlist":[{"username":"felord.cn"},{"username":"felordcn"},{"username":"felord"}]}说到这里,你可能会有疑问:Jackson是如何处理泛型问题的?如何获取泛型Class类型通过直接方式获取泛型Class类型是不可能的,但是我们可以获取泛型类型的抽象定义是java.lang.reflect.ParameterizedType,直接使用ParameterizedType不方便。所以在Jackson中,泛型问题可以通过TypeReference来处理。如果我们需要反序列化OjbectResponse我们可以:.readValue(json,newTypeReference>(){});其实对应的Spring也提供了一个类似的工具类org.springframework.core.ParameterizedTypeReference,特别是如果你使用RestTemplate来请求第三方的时候有时会用到这个通用的处理工具。