I usually post about Jackson and JSON stuff on Google+ - you can follow me there:
1. Overview
In this tutorial, we’ll go over how to use Jackson JSON Views to serialize/deserialize objects, customize the views and finally – how to start integrating with Spring.
2. Serialize using JSON Views
First – let’s go through a simple example – serialize an object with @JsonView.
Here is our view:
public class Views { public static class Public { } }
And the “User” entity:
public class User { public int id; @JsonView(Views.Public.class) public String name; }
Now let’s serialize a “User” instance using our view:
@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"))); }
Note how, because we’re serializing with a specific view active, we’re seeing only the right fields being serialized.
It’s also important to understand, that – by default – all properties not explicitly marked as being part of a view, are serialized. We are disabling that behavior with the handy DEFAULT_VIEW_INCLUSION feature.
3. Use Multiple JSON Views
Next – let’s see how to use multiple JSON Views – each has different fields as in the following example:
Here we have to views where Internal extends Public, with the internal view extending the public one:
public class Views { public static class Public { } public static class Internal extends Public { } }
And here is our entity “Item” where only the fields id and name are included in the Public view:
public class Item { @JsonView(Views.Public.class) public int id; @JsonView(Views.Public.class) public String itemName; @JsonView(Views.Internal.class) public String ownerName; }
If we use the Public view to serialize – only id and name will be serialized to 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"))); }
But if we use the Internal view to perform the serialization, all fields will be part of the JSON output:
@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. Deserialize using JSON Views
Now – let’s see how to use JSON Views to deserialize objects – specifically, a User instance:
@Test public void whenUseJsonViewToDeserialize_thenCorrect() throws IOException { String json = "{\"id\":1,\"name\":\"John\"}"; ObjectMapper mapper = new ObjectMapper(); User user = mapper.readerWithView(Views.Public.class) .withType(User.class) .readValue(json); assertEquals(1, user.getId()); assertEquals("John", user.getName()); }
Note how we’re using the readerWithView() API to create an ObjectReader using the given view.
5. Customize JSON Views
Next – let’s see how to customize JSON Views. In the next example – we want to make the User “name” UpperCase in the serialization result.
We will use BeanPropertyWriter and BeanSerializerModifier to customize our JSON view. First – here is the BeanPropertyWriter UpperCasingWriter to transform the User name to upper case:
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); } }
And here is the BeanSerializerModifier to set the User name BeanPropertyWriter with our custom UpperCasingWriter:
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; } }
Now – let’s serialize a User instance using the modified Serializer:
@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. Using JSON Views with Spring
Finally – let’s take a quick look at using JSON views with the Spring Framework. We can leverage the @JsonView annotation to customize our JSON response at the API level.
In the following example – we used the Public view to respond:
@JsonView(Views.Public.class) @RequestMapping("/items/{id}") public Item getItemPublic(@PathVariable int id) { return ItemManager.getById(id); }
The response is:
{"id":2,"itemName":"book"}
And when we used the Internal view as follows:
@JsonView(Views.Internal.class) @RequestMapping("/items/internal/{id}") public Item getItemInternal(@PathVariable int id) { return ItemManager.getById(id); }
That was the response:
{"id":2,"itemName":"book","ownerName":"John"}
If you want to dive deeper into using the views with Spring 4.1, you should check out the Jackson improvements in Spring 4.1.
7. Conclusion
In this quick tutorial, we had a look at the Jackson JSON views and the @JsonView annotation. We learned how to use JSON Views to have fine-grained control over our serialize/deserialize process – using a single or multiple views.
I usually post about Jackson and JSON stuff on Google+ - you can follow me there: