Jackson JSON 视图
1. 概述
在本教程中,我们将介绍如何使用 Jackson JSON 视图来序列化/反序列化对象、自定义视图以及最后 - 如何开始与 Spring 集成。
2. 使用 JSON 视图进行序列化
首先——让我们看一个简单的例子——用***@JsonView*序列化一个对象**。 这是我们的观点:
public class Views {
public static class Public {
}
}
和“用户”实体:
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 视图
接下来——让我们看看如何使用多个 JSON 视图——每个都有不同的字段,如下例所示: 在这里,我们必须查看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 视图反序列化
现在——让我们看看如何使用 JSON 视图来反序列化对象——特别是一个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 视图
接下来——让我们看看如何自定义 JSON 视图。在下一个示例中——我们希望在序列化结果中将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;
}
}
现在——让我们使用修改后的序列化器序列化一个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 视图
最后——让我们快速了解一下在Spring Framework中使用 JSON 视图。我们可以利用*@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 改进 。