Appearance
Jackson 4-使用@JsonView
本文介绍如何在Jackson中@JsonView的用法以及@JsonView在Spring中的用法。参考链接:https://www.baeldung.com/jackson-json-view-annotation
1. 使用@JsonView进行序列化
@JsonView的作用是当序列化一个类时,只序列化其中某些字段。虽然@JsonIgnore也可以实现该目的,但@JsonView可定义多个视图,每个视图可序列化不同的字段。
首先准备基础类和测试方法:
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods {
private int id;
private String goodsCode;
private String goodsName;
private String unit;
private String spec;
private BigDecimal price;
// 成本价
private BigDecimal costPrice;
// 库存
private int stock;
}java
@Test
void test03() throws JsonProcessingException {
Goods goods = new Goods(
1,
"1001",
"手机",
"部",
"12GB+1TB",
new BigDecimal(6000),
new BigDecimal(4800),
1000
);
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = objectMapper.writeValueAsString(goods);
System.out.println(jsonString);
}结果显而易见,所有字段都序列化了:
txt
{"id":1,"goodsCode":"1001","goodsName":"手机","unit":"部","spec":"12GB+1TB","price":6000,"costPrice":4800,"stock":1000}如果我们使用@JsonView,就可以定义不同的序列化结果了。首先定义视图,视图就是一个类,我们定义在Goods类中:
java
public class Goods {
// 表示外部需要的视图
public static class OuterJsonView{}
// 表示内部需要的视图,继承自外部视图
public static class InnerJsonView extends OuterJsonView{}
}然后使用@JsonView在字段上定义该字段属于哪个视图:
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods {
@JsonView(InnerJsonView.class)
private int id;
@JsonView(OuterJsonView.class)
private String goodsCode;
@JsonView(OuterJsonView.class)
private String goodsName;
@JsonView(OuterJsonView.class)
private String unit;
@JsonView(OuterJsonView.class)
private String spec;
@JsonView(OuterJsonView.class)
private BigDecimal price;
// 成本价
@JsonView(InnerJsonView.class)
private BigDecimal costPrice;
// 库存
@JsonView(OuterJsonView.class)
private int stock;
public static class OuterJsonView{}
public static class InnerJsonView extends OuterJsonView{}
}最后,使用ObjectMapper序列化时,决定使用哪个视图:
java
@Test
void test03() throws JsonProcessingException {
Goods goods = new Goods(
1,
"1001",
"手机",
"部",
"12GB+1TB",
new BigDecimal(6000),
new BigDecimal(4800),
1000
);
ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
String jsonString = objectMapper
.writerWithView(Goods.OuterJsonView.class)
.writeValueAsString(goods);
System.out.println(jsonString);
}txt
{"goodsCode":"1001","goodsName":"手机","unit":"部","spec":"12GB+1TB","price":6000,"stock":1000}- 注意,第18行指定了要使用的视图;
- 第15行的配置
MapperFeature.DEFAULT_VIEW_INCLUSION是指,如果字段没有标注@JsonView,那么在所有的视图中是否应该包含,默认情况下开启,也可以使用第15行关闭该配置。
2. 使用@JsonView进行反序列化
java
@Test
void test04() throws IOException {
String jsonString = "{\"goodsCode\":\"1001\",\"goodsName\":\"手机\",\"unit\":\"部\",\"spec\":\"12GB+1TB\",\"price\":6000,\"stock\":1000}";
ObjectMapper objectMapper = new ObjectMapper();
Goods goods = objectMapper.readerWithView(Goods.OuterJsonView.class)
.readValue(jsonString, Goods.class);
System.out.println(goods);
}好像用处不大,直接反序列化也可以,缺少的字段赋默认值。
3. 在Spring中使用@JsonView
我们可以在控制器的方法上标注@JsonView来指定使用的视图。
java
@RestController
public class GoodsController {
@GetMapping("/goods/{id}")
@JsonView(Goods.OuterJsonView.class)
public Goods getGoodsById(@PathVariable("id") int id) {
Goods goods = new Goods(
id,
"1001",
"手机",
"部",
"12GB+1TB",
new BigDecimal(6000),
new BigDecimal(4800),
1000
);
return goods;
}
}在方法上标注@JsonView可以控制返回对象的不同视图。
但是,我们希望在控制器中返回统一的结构,例如:
java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class R<T> {
private int code;
private String msg;
private T data;
public static <T> R ok(T data){
return new R<T>(1, "success", data);
}
public static <T> R error(String msg, T data){
return new R<T>(-1, msg, data);
}
}我们想要控制的数据视图是统一返回结构的字段,这要如何实现呢?