Jackson JSON Views
最后更新:2020年2月12日
1. 概述
在本教程中,我们将了解如何使用 Jackson JSON Views 来序列化/反序列化对象,自定义视图,最后 – 如何开始与 Spring 集成。
2. 使用 JSON Views 序列化
首先 – 让我们看一个简单的例子 – 使用 @JsonView 序列化一个对象。
这是我们的视图
public class Views {
public static class Public {
}
}
以及 “User” 实体
public class User {
public int id;
@JsonView(Views.Public.class)
public String name;
}
现在让我们使用我们的视图序列化一个 “User” 实例
@Test
public void whenUseJsonViewToSerialize_thenCorrect()
throws JsonProcessingException {
User user = new User(1, "John");
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
String result = mapper
.writerWithView(Views.Public.class)
.writeValueAsString(user);
assertThat(result, containsString("John"));
assertThat(result, not(containsString("1")));
}
请注意,由于我们正在使用激活的特定视图进行序列化,我们看到 只有正确的字段被序列化。
同样重要的是要理解,默认情况下 – 所有未显式标记为视图一部分的属性都会被序列化。我们使用方便的 DEFAULT_VIEW_INCLUSION 功能禁用此行为。
3. 使用多个 JSON Views
接下来 – 让我们看看如何使用多个 JSON Views – 每个视图具有不同的字段,如以下示例所示
这里有两个视图,其中 Internal 扩展了 Public,内部视图扩展了公共视图
public class Views {
public static class Public {
}
public static class Internal extends Public {
}
}
这是我们的实体 “Item”,其中只有字段 id 和 name 包含在 Public 视图中
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
如果使用 Public 视图进行序列化 – 只有 id 和 name 将序列化为 JSON
@Test
public void whenUsePublicView_thenOnlyPublicSerialized()
throws JsonProcessingException {
Item item = new Item(2, "book", "John");
ObjectMapper mapper = new ObjectMapper();
String result = mapper
.writerWithView(Views.Public.class)
.writeValueAsString(item);
assertThat(result, containsString("book"));
assertThat(result, containsString("2"));
assertThat(result, not(containsString("John")));
}
但是,如果使用 Internal 视图执行序列化,所有字段都将包含在 JSON 输出中
@Test
public void whenUseInternalView_thenAllSerialized()
throws JsonProcessingException {
Item item = new Item(2, "book", "John");
ObjectMapper mapper = new ObjectMapper();
String result = mapper
.writerWithView(Views.Internal.class)
.writeValueAsString(item);
assertThat(result, containsString("book"));
assertThat(result, containsString("2"));
assertThat(result, containsString("John"));
}
4. 使用 JSON Views 反序列化
现在 – 让我们看看如何使用 JSON Views 来反序列化对象 – 特别是,一个 User 实例
@Test
public void whenUseJsonViewToDeserialize_thenCorrect()
throws IOException {
String json = "{"id":1,"name":"John"}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper
.readerWithView(Views.Public.class)
.forType(User.class)
.readValue(json);
assertEquals(1, user.getId());
assertEquals("John", user.getName());
}
请注意,我们正在使用 readerWithView() API 使用给定的视图创建一个 ObjectReader。
5. 自定义 JSON Views
接下来 – 让我们看看如何自定义 JSON Views。在下一个示例中 – 我们希望在序列化结果中使 User 的 “name” 大写。
我们将使用 BeanPropertyWriter 和 BeanSerializerModifier 来自定义我们的 JSON 视图。首先 – 这是 BeanPropertyWriter UpperCasingWriter,用于将 User 的 name 转换为大写
public class UpperCasingWriter extends BeanPropertyWriter {
BeanPropertyWriter _writer;
public UpperCasingWriter(BeanPropertyWriter w) {
super(w);
_writer = w;
}
@Override
public void serializeAsField(Object bean, JsonGenerator gen,
SerializerProvider prov) throws Exception {
String value = ((User) bean).name;
value = (value == null) ? "" : value.toUpperCase();
gen.writeStringField("name", value);
}
}
这是 BeanSerializerModifier,用于使用我们自定义的 UpperCasingWriter 设置 User name BeanPropertyWriter
public class MyBeanSerializerModifier extends BeanSerializerModifier{
@Override
public List<BeanPropertyWriter> changeProperties(
SerializationConfig config, BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
for (int i = 0; i < beanProperties.size(); i++) {
BeanPropertyWriter writer = beanProperties.get(i);
if (writer.getName() == "name") {
beanProperties.set(i, new UpperCasingWriter(writer));
}
}
return beanProperties;
}
}
现在 – 让我们使用修改后的 Serializer 序列化一个 User 实例
@Test
public void whenUseCustomJsonViewToSerialize_thenCorrect()
throws JsonProcessingException {
User user = new User(1, "John");
SerializerFactory serializerFactory = BeanSerializerFactory.instance
.withSerializerModifier(new MyBeanSerializerModifier());
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializerFactory(serializerFactory);
String result = mapper
.writerWithView(Views.Public.class)
.writeValueAsString(user);
assertThat(result, containsString("JOHN"));
assertThat(result, containsString("1"));
}
6. 在 Spring 中使用 JSON Views
最后 – 让我们快速了解如何在 Spring Framework 中使用 JSON views。我们可以利用 @JsonView 注解来在 API 级别自定义我们的 JSON 响应。
在下面的示例中 – 我们使用了 Public 视图来响应
@JsonView(Views.Public.class)
@RequestMapping("/items/{id}")
public Item getItemPublic(@PathVariable int id) {
return ItemManager.getById(id);
}
响应是
{"id":2,"itemName":"book"}
当我们使用 Internal 视图如下时
@JsonView(Views.Internal.class)
@RequestMapping("/items/internal/{id}")
public Item getItemInternal(@PathVariable int id) {
return ItemManager.getById(id);
}
这是响应
{"id":2,"itemName":"book","ownerName":"John"}
如果您想深入了解在 Spring 4.1 中使用视图,您应该查看 Spring 4.1 中的 Jackson 改进。
7. 结论
在本快速教程中,我们了解了 Jackson JSON views 和 @JsonView 注解。我们展示了如何使用 JSON Views 对我们的序列化/反序列化过程进行细粒度控制 – 使用单个或多个视图。
支持本文的代码可在 GitHub 上获取。 一旦你以 Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。
















