前言
前面介绍了Jackson序列化和反序列化相关的注解;
本篇再介绍几个比较常用的注解;
其实这里面的注解之前的文章也有提到过,只是在这里做个总结,为了方便;
目录
- @JsonProperty
- @JsonFormat
- @JsonUnwrapped
- @JsonView
正文
1. @JsonProperty
这个注解是用来将Json字符串中的属性名和Java类中的属性名对应起来;
功能上类似前面序列化和反序列化中介绍的@JsonGetter和@JsonSetter,可以认为这个注解是他俩的合体;
下面我们看个例子,实体类User如下:
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private String username;
@JsonProperty(value = "name")
public void setUsername(String name){
this.username = name;
}
@JsonProperty(value = "name")
public String getUsername(){
return this.username;
}
}
假设Json字符串中的属性名为name,而这里的User类的属性名为username;
为了使他们在序列化和反序列化时,能够一一对应,这里我们在setter和getter方法上都加了@JsonProperty注解;
这样就可以给name和username建立一个映射关系;
下面是测试代码:
ObjectMapper objectMapper = new ObjectMapper();
User jalon = new User("jalon");
String s = objectMapper.writeValueAsString(jalon);
System.out.println(s);
输出为:{"name":"jalon"}
如果我们想要反序列化,也是可以的,代码如下:
User user = objectMapper.readValue(s, User.class);
System.out.println(user);
输出为:User(username=jalon)
可以看到,不管是序列化还是反序列化,@JsonProperty都可以完美的处理属性之间的映射关系;
2. @JsonFormat
这个注解在Jackson处理日期 - 掘金 (juejin.cn)中介绍过;
它主要是用来处理java.util.Date日期;
我们还是以上面的User为例,在它的基础上加一个birth属性,如下所示:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birth;
然后测试代码中,构造User时多传入一个new Date()即可,如下所示:
ObjectMapper objectMapper = new ObjectMapper();
User jalon = new User("jalon", new Date());
String s = objectMapper.writeValueAsString(jalon);
System.out.println(s);
输出为:{"birth":"2022-02-22 09:16:48","name":"jalon"}
可以看到,birth属性确实按照我们设置的默认进行输出了,但是时间不准;
这是因为时区没有配置,重新修改birth属性,如下所示:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date birth;
此时输出正常:{"birth":"2022-02-22 17:20:37","name":"jalon"}
3. @JsonUnwrapped
当Java类属性有嵌套的对象时,可以用这个注解,将嵌套的对象平铺展开;
这里我们创建一个Animal类,然后将其添加到User类的属性中,如下所示:
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private String username;
private Animal animal;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal{
private String animalName;
}
这里我们先不加注解@JsonUnwrapped,看下是什么效果,测试代码如下:
ObjectMapper objectMapper = new ObjectMapper();
User jalon = new User("jalon",new Animal("tutu"));
String s = objectMapper.writeValueAsString(jalon);
System.out.println(s);
输出如下:
可以看到,嵌套的Animal是以内置对象的方式进行展示;
为了直观显示,我们加上@JsonUnwrapped试试,加了注解的animal属性代码如下:
@JsonUnwrapped
private Animal animal;
再次运行,输出如下:
可以看到,内置的animal被展开了,此时看起来会比较清晰明了;
此时反序列化还是可以组装回去的,即:
加了@JsonUnwrapped注解后:
-
序列化可以对嵌套的对象进行展开处理;
-
反序列化还可以对展开的对象进行折叠处理;
如果属性名有冲突怎么办呢?
有冲突也不影响序列化的正常输出,但是会影响反序列化的解析;
假设我们把他们的属性设置为一致,如下所示:
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal{
private String username;
}
那么还是可以正常序列化,运行测试代码,结果如下:
但是反序列化就会出问题,数据错乱,测试代码如下:
User user = objectMapper.readValue(s, User.class);
System.out.println(user);
结果如下:
可以看到,结果乱了;
所以建议如果属性有重名的,不要用这个@JsonUnwrapped注解,以免造成数据混乱
4. @JsonView
这个注解类似前面介绍的Jackson如何隐藏字段 - 掘金 (juejin.cn),目的都是为了修改属性的可见性;
不过这个注解会比较麻烦一点,需要自己定义对应的类;
如下所示:我们定义一个View类,其中有Visible和Invisible两个内部类
public class View {
public static class Visible{}
public static class Invisible{}
}
然后在User类中进行配置:这里username属性加了View.Visible,而animal加了View.Invisble
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
@JsonView(View.Visible.class)
private String username;
@JsonView(View.Invisible.class)
private Animal animal;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal{
private String animalName;
}
最后在测试代码的ObjectMapper中进行注册对应的View类,如下所示:
ObjectMapper objectMapper = new ObjectMapper();
User jalon = new User("jalon",new Animal("tutu"));
String s = objectMapper.writerWithView(View.Visible.class).writeValueAsString(jalon);
System.out.println(s);
此时运行输出如下:
可以看到,animal被隐藏了,只输出了username属性;
总结
本篇介绍了几种常用的Jackson注解,包括:
- @JsonProperty: 用来解决属性名不匹配的情况
- @JsonFormat: 用来格式化 java.util.Date 日期
- @JsonUnwrapped: 用来展开/折叠嵌套的对象,
- @JsonView: 用来动态修改属性的可见性
评论区