Jackson API
Jackson API
JSON
1: Jackson Annotation Examples
1. Overview 1
2. Maven Dependencies 2
3.1. @JsonAnyGetter 3
3.2. @JsonGetter 4
3.3. @JsonPropertyOrder 5
3.4. @JsonRawValue 6
3.5. @JsonValue 7
3.6. @JsonRootName 8
3.6. @JsonRootName 11
4.1. @JsonCreator 13
4.2. @JacksonInject 14
4.3. @JsonAnySetter 15
4.4. @JsonSetter 16
4.5. @JsonDeserialize 17
4.6. @JsonAlias 18
6.1. @JsonProperty 29
6.2. @JsonFormat 31
6.3. @JsonUnwrapped 32
6.4. @JsonView 34
6.6. @JsonIdentityInfo 38
6.7. @JsonFilter 40
3. Advanced Features 54
4. Conclusion 62
3: Jackson Ignore Properties on Marshalling
1. Overview 64
6. Conclusion 70
4. Conclusion 75
5: Jackson – Change Name of Field
1. Overview 77
3. Conclusion 80
4. Conclusion 88
1: Jackson Annotation Examples
7
1. Overview
1
2. Maven Dependencies
1. <dependency>
2. <groupId>com.fasterxml.jackson.core</groupId>
3. <artifactId>jackson-databind</artifactId>
4. <version>2.9.8</version>
5. </dependency>
This dependency will also transitively add the following libraries to the
classpath:
1. jackson-annotations-2.9.8.jar
2. jackson-core-2.9.8.jar
3. jackson-databind-2.9.8.jar
2
3. Jackson Serialization Annotations
3.1. @JsonAnyGetter
Here’s a quick example – the ExtendableBean entity has the name property
and a set of extendable attributes in the form of key/value pairs:
When we serialize an instance of this entity, we get all the key-values in the
Map as standard, plain properties:
1. {
2. “name”:”My bean”,
3. “attr2”:”val2”,
4. “attr1”:”val1”
5. }
3
And here how the serialization of this entity looks like in practice:
1. @Test
2. public void whenSerializingUsingJsonAnyGetter_thenCorrect()
3. throws JsonProcessingException {
4.
5. ExtendableBean bean = new ExtendableBean(“My bean”);
6. bean.add(“attr1”, “val1”);
7. bean.add(“attr2”, “val2”);
8.
9. String result = new ObjectMapper().writeValueAsString(bean);
10.
11. assertThat(result, containsString(“attr1”));
12. assertThat(result, containsString(“val1”));
13. }
3.2. @JsonGetter
4
And here’s how this works in practice:
1. @Test
2. public void whenSerializingUsingJsonGetter_thenCorrect()
3. throws JsonProcessingException {
4.
5. MyBean bean = new MyBean(1, “My bean”);
6.
7. String result = new ObjectMapper().writeValueAsString(bean);
8.
9. assertThat(result, containsString(“My bean”));
10. assertThat(result, containsString(“1”));
11. }
3.3. @JsonPropertyOrder
1. {
2. “name”:”My bean”,
3. “id”:1
4. }
5
And a simple test:
1. @Test
2. public void whenSerializingUsingJsonPropertyOrder_thenCorrect()
3. throws JsonProcessingException {
4.
5. MyBean bean = new MyBean(1, “My bean”);
6.
7. String result = new ObjectMapper().writeValueAsString(bean);
8. assertThat(result, containsString(“My bean”));
9. assertThat(result, containsString(“1”));
10. }
1. {
2. “id”:1,
3. “name”:”My bean”
4. }
3.4. @JsonRawValue
6
The output of serializing the entity is:
1. {
2. “name”:”My bean”,
3. “json”:{
4. “attr”:false
5. }
6. }
1. @Test
2. public void whenSerializingUsingJsonRawValue_thenCorrect()
3. throws JsonProcessingException {
4.
5. RawBean bean = new RawBean(“My bean”, “{“attr”:false}”);
6.
7. String result = new ObjectMapper().writeValueAsString(bean);
8. assertThat(result, containsString(“My bean”));
9. assertThat(result, containsString(“{“attr”:false}”));
10. }
We can also use the optional boolean argument value that defines whether
this annotation is active or not.
3.5. @JsonValue
@JsonValue indicates a single method that the library will use to serialize
the entire instance.
7
1. public enum TypeEnumWithValue {
2. TYPE1(1, “Type A”), TYPE2(2, “Type 2”);
3.
4. private Integer id;
5. private String name;
6.
7. // standard constructors
8.
9. @JsonValue
10. public String getName() {
11. return name;
12. }
13. }
Our test:
1. @Test
2. public void whenSerializingUsingJsonValue_thenCorrect()
3. throws JsonParseException, IOException {
4.
5. String enumAsString = new ObjectMapper()
6. .writeValueAsString(TypeEnumWithValue.TYPE1);
7.
8. assertThat(enumAsString, is(“”Type A””));
9. }
3.6. @JsonRootName
1. {
2. “id”: 1,
3. “name”: “John”
4. }
8
It’s going to be wrapped like this:
1. {
2. “User”: {
3. “id”: 1,
4. “name”: “John”
5. }
6. }
1. @JsonRootName(value = “user”)
2. public class UserWithRoot {
3. public int id;
4. public String name;
5. }
1. @Test
2. public void whenSerializingUsingJsonRootName_thenCorrect()
3. throws JsonProcessingException {
4.
5. UserWithRoot user = new User(1, “John”);
6.
7. ObjectMapper mapper = new ObjectMapper();
8. mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
9. String result = mapper.writeValueAsString(user);
10.
11. assertThat(result, containsString(“John”));
12. assertThat(result, containsString(“user”));
13. }
9
Here is the output of serialization:
1. {
2. “user”:{
3. “id”:1,
4. “name”:”John”
5. }
6. }
1. <user xmlns=”users”>
2. <id xmlns=””>1</id>
3. <name xmlns=””>John</name>
4. <items xmlns=””/>
5. </user>
10
3.6. @JsonRootName
11
Let’s use these in a test:
1. @Test
2. public void whenSerializingUsingJsonSerialize_thenCorrect()
3. throws JsonProcessingException, ParseException {
4.
5. SimpleDateFormat df
6. = new SimpleDateFormat(“dd-MM-yyyy hh:mm:ss”);
7.
8. String toParse = “20-12-2014 02:30:00”;
9. Date date = df.parse(toParse);
10. Event event = new Event(“party”, date);
11.
12. String result = new ObjectMapper().writeValueAsString(event);
13. assertThat(result, containsString(toParse));
14. }
12
4. Jackson Deserialization Annotations
4.1. @JsonCreator
It’s very helpful when we need to deserialize some JSON that doesn’t exactly
match the target entity we need to get.
1. {
2. “id”:1,
3. “theName”:”My bean”
4. }
13
Let’s see this in action:
1. @Test
2. public void whenDeserializingUsingJsonCreator_thenCorrect()
3. throws IOException {
4. String json = “{\”id\”:1,\”theName\”:\”My bean\”}”;
5. BeanWithCreator bean = new ObjectMapper()
6. .readerFor(BeanWithCreator.class)
7. .readValue(json);
8. assertEquals(“My bean”, bean.name);
9. }
4.2. @JacksonInject
@JacksonInject indicates that a property will get its value from the injection
and not from the JSON data.
1. @Test
2. public void whenDeserializingUsingJsonInject_thenCorrect()
3. throws IOException {
4. String json = “{\”name\”:\”My bean\”}”;
5. InjectableValues inject = new InjectableValues.Std()
6. .addValue(int.class, 1);
7. BeanWithInject bean = new ObjectMapper().reader(inject)
8. .forType(BeanWithInject.class)
9. .readValue(json);
10. assertEquals(“My bean”, bean.name);
11. assertEquals(1, bean.id);
12. }
14
4.3. @JsonAnySetter
Let’s see how this works – we’ll use @JsonAnySetter to deserialize the entity
ExtendableBean:
1. {
2. “name”:”My bean”,
3. “attr2”:”val2”,
4. “attr1”:”val1”
5. }
1. @Test
2. public void whenDeserializingUsingJsonAnySetter_thenCorrect()
3. throws IOException {
4. String json
5. = “{\”name\”:\”My
6. bean\”,\”attr2\”:\”val2\”,\”attr1\”:\”val1\”}”;
7. ExtendableBean bean = new ObjectMapper()
8. .readerFor(ExtendableBean.class)
9. .readValue(json);
10. assertEquals(“My bean”, bean.name);
11. assertEquals(“val2”, bean.getProperties().get(“attr2”));
12. }
15
4.4. @JsonSetter
This is super useful when we need to read some JSON data but the target
entity class doesn’t exactly match that data, and so we need to tune the
process to make it fit.
Now, when we need to unmarshall some JSON data – this works perfectly
well:
1. @Test
2. public void whenDeserializingUsingJsonSetter_thenCorrect()
3. throws IOException {
4.
5. String json = “{\”id\”:1,\”name\”:\”My bean\”}”;
6.
7. MyBean bean = new ObjectMapper()
8. .readerFor(MyBean.class)
9. .readValue(json);
10. assertEquals(“My bean”, bean.getTheName());
11. }
16
4.5. @JsonDeserialize
Let’s see how that plays out – we’ll use @JsonDeserialize to deserialize the
eventDate property with the CustomDateDeserializer:
17
And here’s the back-to-back test:
1. @Test
2. public void whenDeserializingUsingJsonDeserialize_thenCorrect()
3. throws IOException {
4. String json
5. = “{“name”:”party”,”eventDate”:”20-12-2014 02:30:00”}”;
6.
7. SimpleDateFormat df
8. = new SimpleDateFormat(“dd-MM-yyyy hh:mm:ss”);
9. Event event = new ObjectMapper()
10. .readerFor(Event.class)
11. .readValue(json);
12. assertEquals(
13. “20-12-2014 02:30:00”, df.format(event.eventDate));
14. }
4.6. @JsonAlias
The @JsonAlias defines one or more alternative names for a property during
deserialization. Let’s see how this annotation works with a quick example:
Here, we have a POJO and we want to deserialize JSON with values such as
fName, f_name, and firstName into the firstName variable of the POJO.
And here is a test making sure this annotation works as expected :
1. @Test
2. public void whenDeserializingUsingJsonAlias_thenCorrect() throws
3. IOException {
4. String json = “{\”fName\”: \”John\”, \”lastName\”:
5. \”Green\”}”;
6. AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.
7. class).readValue(json);
8. assertEquals(“John”, aliasBean.getFirstName());
9. }
18
5. Jackson Polymorphic Type Handling Annotations
Let’s look at a more complex example and use all three – @JsonTypeInfo,
@JsonSubTypes, and @JsonTypeName – to serialize/deserialize the entity
Zoo:
19
When we do serialization:
1. @Test
2. public void whenSerializingPolymorphic_thenCorrect()
3. throws JsonProcessingException {
4. Zoo.Dog dog = new Zoo.Dog(“lacy”);
5. Zoo zoo = new Zoo(dog);
6.
7. String result = new ObjectMapper()
8. .writeValueAsString(zoo);
9.
10. assertThat(result, containsString(“type”));
11. assertThat(result, containsString(“dog”));
12. }
Here’s what serializing the Zoo instance with the Dog will result in:
1. {
2. “animal”: {
3. “type”: “dog”,
4. “name”: “lacy”,
5. “barkVolume”: 0
6. }
7. }
Now for de-serialization – let’s start with the following JSON input:
1. {
2. “animal”:{
3. “name”:”lacy”,
4. “type”:”cat”
5. }
6. }
20
And let’s see how that gets unmarshalled to a Zoo instance:
1. @Test
2. public void whenDeserializingPolymorphic_thenCorrect()
3. throws IOException {
4. String json =
5. “{\”animal\”:{\”name\”:\”lacy\”,\”type\”:\”cat\”}}”;
6.
7. Zoo zoo = new ObjectMapper()
8. .readerFor(Zoo.class)
9. .readValue(json);
10.
11. assertEquals(“lacy”, zoo.animal.name);
12. assertEquals(Zoo.Cat.class, zoo.animal.getClass());
13. }
21
6. Jackson General Annotations
6.1. @JsonProperty
Our test:
1. @Test
2. public void whenUsingJsonProperty_thenCorrect()
3. throws IOException {
4. MyBean bean = new MyBean(1, “My bean”);
5. String result = new ObjectMapper().writeValueAsString(bean);
6.
7. assertThat(result, containsString(“My bean”));
8. assertThat(result, containsString(“1”));
9.
10. MyBean resultBean = new ObjectMapper()
11. .readerFor(MyBean.class)
12. .readValue(result);
13. assertEquals(“My bean”, resultBean.getTheName());
14. }
22
6.2. @JsonFormat
1. @Test
2. public void whenSerializingUsingJsonFormat_thenCorrect()
3. throws JsonProcessingException, ParseException {
4. SimpleDateFormat df = new SimpleDateFormat(“dd-MM-yyyy
5. hh:mm:ss”);
6. df.setTimeZone(TimeZone.getTimeZone(“UTC”));
7.
8. String toParse = “20-12-2014 02:30:00”;
9. Date date = df.parse(toParse);
10. Event event = new Event(“party”, date);
11.
12. String result = new ObjectMapper().writeValueAsString(event);
13.
14. assertThat(result, containsString(toParse));
15. }
23
6.3. @JsonUnwrapped
Let’s see exactly how that works; we’ll use the annotation to unwrap the
property name:
1. @Test
2. public void whenSerializingUsingJsonUnwrapped_thenCorrect()
3. throws JsonProcessingException, ParseException {
4. UnwrappedUser.Name name = new UnwrappedUser.Name(“John”, “Doe”);
5. UnwrappedUser user = new UnwrappedUser(1, name);
6.
7. String result = new ObjectMapper().writeValueAsString(user);
8.
9. assertThat(result, containsString(“John”));
10. assertThat(result, not(containsString(“name”)));
11. }
Here’s how the output looks like – the fields of the static nested class
unwrapped along with the other field:
1. {
2. “id”:1,
3. “firstName”:”John”,
4. “lastName”:”Doe”
5. }
24
6.4. @JsonView
@JsonView indicates the View in which the property will be included for
serialization/deserialization.
An example will show exactly how that works – we’ll use @JsonView to
serialize an instance of Item entity. Let’s start with the views:
1. @Test
2. public void whenSerializingUsingJsonView_thenCorrect()
3. throws JsonProcessingException {
4. Item item = new Item(2, “book”, “John”);
5.
6. String result = new ObjectMapper()
7. .writerWithView(Views.Public.class)
8. .writeValueAsString(item);
9.
10. assertThat(result, containsString(“book”));
11. assertThat(result, containsString(“2”));
12. assertThat(result, not(containsString(“John”)));
13. }
25
6.5. @JsonManagedReference, @JsonBackReference
1. @Test
2. public void whenSerializingUsingJacksonReferenceAnnotation_
3. thenCorrect()
4. throws JsonProcessingException {
5. UserWithRef user = new UserWithRef(1, “John”);
6. ItemWithRef item = new ItemWithRef(2, “book”, user);
7. user.addItem(item);
8. String result = new ObjectMapper().writeValueAsString(item);
9.
10. assertThat(result, containsString(“book”));
11. assertThat(result, containsString(“John”));
12. assertThat(result, not(containsString(“userItems”)));
13. }
26
6.6. @JsonIdentityInfo
1. @JsonIdentityInfo(
2. generator = ObjectIdGenerators.PropertyGenerator.class,
3. property = “id”)
4.
5. public class ItemWithIdentity {
6.
7. public int id;
8. public String itemName;
9. public UserWithIdentity owner;
10. }
1. @JsonIdentityInfo(
2. generator = ObjectIdGenerators.PropertyGenerator.class,
3. property = “id”)
4.
5. public class UserWithIdentity {
6.
7. public int id;
8. public String name;
9. public List<ItemWithIdentity> userItems;
10. }
27
Now, let’s see how the infinite recursion problem is handled:
1. @Test
2. public void whenSerializingUsingJsonIdentityInfo_thenCorrect()
3. throws JsonProcessingException {
4. UserWithIdentity user = new UserWithIdentity(1, “John”);
5. ItemWithIdentity item = new ItemWithIdentity(2, “book”, user);
6. user.addItem(item);
7. String result = new ObjectMapper().writeValueAsString(item);
8. assertThat(result, containsString(“book”));
9. assertThat(result, containsString(“John”));
10. assertThat(result, containsString(“userItems”));
11. }
1. {
2. “id”: 2,
3. “itemName”: “book”,
4. “owner”: {
5. “id”: 1,
6. “name”: “John”,
7. “userItems”: [
8. 2
9. ]
10. }
11. }
6.7. @JsonFilter
Let’s take a look at an example; first, we define the entity, and we point to
the filter:
1. @JsonFilter(“myFilter”)
2. public class BeanWithFilter {
3. public int id;
4. public String name;
5. }
28
Now, in the full test, we define the filter – which excludes all other properties
except name from serialization:
1. @Test
2. public void whenSerializingUsingJsonFilter_thenCorrect()
3. throws JsonProcessingException {
4. BeanWithFilter bean = new BeanWithFilter(1, “My bean”);
5.
6. FilterProvider filters
7. = new SimpleFilterProvider().addFilter(
8. “myFilter”,
9. SimpleBeanPropertyFilter.filterOutAllExcept(“name”));
10.
11. String result = new ObjectMapper()
12. .writer(filters)
13. .writeValueAsString(bean);
14.
15. assertThat(result, containsString(“My bean”));
16. assertThat(result, not(containsString(“id”)));
17. }
29
7. Custom Jackson Annotation
Next, let’s see how to create a custom Jackson annotation. We can make
use of the @JacksonAnnotationsInside annotation:
1. @Retention(RetentionPolicy.RUNTIME)
2. @JacksonAnnotationsInside
3. @JsonInclude(Include.NON_NULL)
4. @JsonPropertyOrder({ “name”, “id”, “dateCreated” })
5. public @interface CustomAnnotation {}
1. @CustomAnnotation
2. public class BeanWithCustomAnnotation {
3. public int id;
4. public String name;
5. public Date dateCreated;
6. }
We can see how it does combine the existing annotations into a simpler,
custom one that we can use as a shorthand:
1. @Test
2. public void whenSerializingUsingCustomAnnotation_thenCorrect()
3. throws JsonProcessingException {
4. BeanWithCustomAnnotation bean
5. = new BeanWithCustomAnnotation(1, “My bean”, null);
6. String result = new ObjectMapper().writeValueAsString(bean);
7. assertThat(result, containsString(“My bean”));
8. assertThat(result, containsString(“1”));
9. assertThat(result, not(containsString(“dateCreated”)));
10. }
1. {
2. “name”:”My bean”,
3. “id”:1
4. }
30
8. Jackson MixIn Annotations
Let’s use the MixIn annotations to – for example – ignore properties of type
User:
1. @Test
2. public void whenSerializingUsingMixInAnnotation_thenCorrect()
3. throws JsonProcessingException {
4. Item item = new Item(1, “book”, null);
5.
6. String result = new ObjectMapper().writeValueAsString(item);
7. assertThat(result, containsString(“owner”));
8.
9. ObjectMapper mapper = new ObjectMapper();
10. mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
11.
12. result = mapper.writeValueAsString(item);
13. assertThat(result, not(containsString(“owner”)));
14. }
31
9. Disable Jackson Annotation
Finally – let’s see how we can disable all Jackson annotations. We can do
this by disabling the MapperFeature.USE_ANNOTATIONS as in the following
example:
1. @JsonInclude(Include.NON_NULL)
2. @JsonPropertyOrder({ “name”, “id” })
3. public class MyBean {
4. public int id;
5. public String name;
6. }
Now, after disabling annotations, these should have no effect and the
defaults of the library should apply:
1. @Test
2. public void whenDisablingAllAnnotations_thenAllDisabled()
3. throws IOException {
4. MyBean bean = new MyBean(1, null);
5.
6. ObjectMapper mapper = new ObjectMapper();
7. mapper.disable(MapperFeature.USE_ANNOTATIONS);
8. String result = mapper.writeValueAsString(bean);
9.
10. assertThat(result, containsString(“1”));
11. assertThat(result, containsString(“name”));
12. }
1. {“id”:1}
1. {
2. “id”:1,
3. “name”:null
4. }
32
10. Conclusion
This chapter has been a deep-dive into Jackson annotations, just scratching
the surface of the kind of flexibility you can get using them correctly.
The implementation of all these examples and code snippets can be found
in the GitHub project.
33
2: Intro to the Jackson ObjectMapper
34
1. Overview
35
2. Reading and Writing Using ObjectMapper
Also, on the writing side of things, we can use the writeValue API to serialize
any Java object as JSON output.
We’ll use the following Car class with two fields as the object to serialize or
deserialize throughout this chapter:
Let’s see a first example of serializing a Java Object into JSON using the
writeValue method of ObjectMapper class:
1. {“color”:”yellow”,”type”:”renault”}
36
The methods writeValueAsString and writeValueAsBytes of ObjectMapper
class generates a JSON from a Java object and returns the generated JSON
as a string or as a byte array:
The readValue() function also accepts other forms of input like a file
containing JSON string:
37
2.4. Creating a Java List from a JSON Array String
e can parse a JSON in the form of an array into a Java object list using a
TypeReference:
1. String jsonCarArray =
2. “[{ \”color\” : \”Black\”, \”type\” : \”BMW\” }, { \”color\” :
3. \”Red\”, \”type\” : \”FIAT\” }]”;
4. List<Car> listCar = objectMapper.readValue(jsonCarArray, new
5. TypeReference<List<Car>>(){});
38
3. Advanced Features
One of the greatest strength of the Jackson library is the highly customizable
serialization and deserialization process.
In this section, we’ll go through some advanced features where the input or
the output JSON response can be different from the object which generates
or consumes the response.
While converting JSON objects to Java classes, in case the JSON string has
some new fields, then the default process will result in an exception:
1. String jsonString
2. = “{ \”color\” : \”Black\”, \”type\” : \”Fiat\”, \”year\” :
3. \”1970\” }”;
The JSON string in the above example in the default parsing process to the
Java object for the Class Car will result in the UnrecognizedPropertyException
exception.
Through the configure method we can extend the default process to ignore
the new fields:
1. objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_
2. PROPERTIES, false);
3. Car car = objectMapper.readValue(jsonString, Car.class);
4. JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
5. JsonNode jsonNodeYear = jsonNodeRoot.get(“year”);
6. String year = jsonNodeYear.asText();
1. objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_
2. PRIMITIVES, false);
39
Similarly, FAIL_ON_NUMBERS_FOR_ENUM controls if enum values are
allowed to be serialized/deserialized as numbers:
1. objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_
2. ENUMS, false);
40
This custom serializer can be invoked like this:
Here’s what the Car looks like (as JSON output) on the client side:
41
And here’s an example of a custom JSON deserializer:
To control the String format of a date, and set it to e.g. yyyy-MM-dd HH:mm
a z, consider the following snippet:
To learn more about serializing dates with Jackson, read our more in-depth
write-up.
42
3.4. Handling Collections
1. String jsonCarArray =
2. “[{ \”color\” : \”Black\”, \”type\” : \”BMW\” }, { \”color\” :
3. \”Red\”, \”type\” : \”FIAT\” }]”;
4. ObjectMapper objectMapper = new ObjectMapper();
5. objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_
6. JSON_ARRAY, true);
7. Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
8. // print cars
Or as a List:
1. String jsonCarArray =
2. “[{ \”color\” : \”Black\”, \”type\” : \”BMW\” }, { \”color\” :
3. \”Red\”, \”type\” : \”FIAT\” }]”;
4. ObjectMapper objectMapper = new ObjectMapper();
5. List<Car> listCar = objectMapper.readValue(jsonCarArray, new
6. TypeReference<List<Car>>(){});
7. // print cars
43
4. Conclusion
The chapter discusses the main features which make the library so popular.
The source code that accompanies the chapter can be found over on GitHub.
44
3: Jackson Ignore Properties on Marshalling
45
1. Overview
This chapter will show how to ignore certain fields when serializing an
object to JSON using Jackson 2.x.
This is very useful when the Jackson defaults aren’t enough and we need to
control exactly what gets serialized to JSON – and there are several ways to
ignore properties.
46
2. Ignore Fields at the Class Level
1. @JsonIgnoreProperties(value = { “intValue” })
2. public class MyDto {
3.
4. private String stringValue;
5. private int intValue;
6. private boolean booleanValue;
7.
8. public MyDto() {
9. super();
10. }
11.
12. // standard setters and getters are not shown
13. }
We can now test that, after the object is written to JSON, the field is indeed
not part of the output:
1. @Test
2. public void givenFieldIsIgnoredByName_whenDtoIsSerialized_
3. thenCorrect()
4. throws JsonParseException, IOException {
5.
6. ObjectMapper mapper = new ObjectMapper();
7. MyDto dtoObject = new MyDto();
8.
9. String dtoAsString = mapper.writeValueAsString(dtoObject);
10.
11. assertThat(dtoAsString, not(containsString(“intValue”)));
12. }
47
3. Ignore Field at the Field Level
We can also ignore a field directly via the @JsonIgnore annotation directly
on the field:
We can now test that the intValue field is indeed not part of the serialized
JSON output:
1. @Test
2. public void givenFieldIsIgnoredDirectly_whenDtoIsSerialized_
3. thenCorrect()
4. throws JsonParseException, IOException {
5.
6. ObjectMapper mapper = new ObjectMapper();
7. MyDto dtoObject = new MyDto();
8.
9. String dtoAsString = mapper.writeValueAsString(dtoObject);
10.
11. assertThat(dtoAsString, not(containsString(“intValue”)));
12. }
48
4. Ignore all Fields by Type
1. @JsonIgnoreType
2. public class SomeType { ... }
More often than not, however, we don’t have control of the class itself; in
this case, we can make good use of Jackson mixins.
First, we define a MixIn for the type we’d like to ignore, and annotate that
with @JsonIgnoreType instead:
1. @JsonIgnoreType
2. public class MyMixInForIgnoreType {}
Then we register that mixin to replace (and ignore) all String[] types during
marshaling:
1. mapper.addMixInAnnotations(String[].class, MyMixInForIgnoreType.
2. class);
49
At this point, all String arrays will be ignored instead of marshaled to JSON:
1. @Test
2. public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_
3. thenCorrect()
4. throws JsonParseException, IOException {
5.
6. ObjectMapper mapper = new ObjectMapper();
7. mapper.addMixIn(String[].class, MyMixInForIgnoreType.class);
8. MyDtoWithSpecialField dtoObject = new
9. MyDtoWithSpecialField();
10. dtoObject.setBooleanValue(true);
11.
12. String dtoAsString = mapper.writeValueAsString(dtoObject);
13.
14. assertThat(dtoAsString, containsString(“intValue”));
15. assertThat(dtoAsString, containsString(“booleanValue”));
16. assertThat(dtoAsString, not(containsString(“stringValue”)));
17. }
Note: Since version 2.5 – it seems that we can not use this method to
ignore primitive data types, but we can use it for custom data types and
arrays.
50
5. Ignore Fields Using Filters
Finally, we can also use filters to ignore specific fields in Jackson. First,
we need to define the filter on the Java object:
1. @JsonFilter(“myFilter”)
2. public class MyDtoWithFilter { ... }
Then, we define a simple filter that will ignore the intValue field:
Now we can serialize the object and make sure that the intValue field is
not present in the JSON output:
1. @Test
2. public final void givenTypeHasFilterThatIgnoresFieldByName_
3. whenDtoIsSerialized_thenCorrect()
4. throws JsonParseException, IOException {
5.
6. ObjectMapper mapper = new ObjectMapper();
7. SimpleBeanPropertyFilter theFilter =
8. SimpleBeanPropertyFilter
9. .serializeAllExcept(“intValue”);
10. FilterProvider filters = new SimpleFilterProvider()
11. .addFilter(“myFilter”, theFilter);
12.
13. MyDtoWithFilter dtoObject = new MyDtoWithFilter();
14. String dtoAsString = mapper.writer(filters).
15. writeValueAsString(dtoObject);
16.
17. assertThat(dtoAsString, not(containsString(“intValue”)));
18. assertThat(dtoAsString, containsString(“booleanValue”));
19. assertThat(dtoAsString, containsString(“stringValue”));
20. System.out.println(dtoAsString);
21. }
51
6. Conclusion
52
4: Ignore Null Fields with Jackson
53
1. Overview
This quick chapter is going to cover how to set up Jackson to ignore null
fields when serializing a java class.
54
2. Ignore Null Fields on the Class
1. @JsonInclude(Include.NON_NULL)
2. public class MyDto { ... }
Now, we should be able to test that null values are indeed not part of the
final JSON output:
1. @Test
2. public void givenNullsIgnoredOnClass_
3. whenWritingObjectWithNullField_thenIgnored()
4. throws JsonProcessingException {
5. ObjectMapper mapper = new ObjectMapper();
6. MyDto dtoObject = new MyDto();
7.
8. String dtoAsString = mapper.writeValueAsString(dtoObject);
9.
10. assertThat(dtoAsString, containsString(“intValue”));
11. assertThat(dtoAsString, not(containsString(“stringValue”)));
12. }
55
3. Ignore Null Fields Globally
1. mapper.setSerializationInclusion(Include.NON_NULL);
Now any null field in any class serialized through this mapper will be
ignored:
1. @Test
2. public void givenNullsIgnoredGlobally_
3. whenWritingObjectWithNullField_thenIgnored()
4. throws JsonProcessingException {
5. ObjectMapper mapper = new ObjectMapper();
6. mapper.setSerializationInclusion(Include.NON_NULL);
7. MyDto dtoObject = new MyDto();
8.
9. String dtoAsString = mapper.writeValueAsString(dtoObject);
10.
11. assertThat(dtoAsString, containsString(“intValue”));
12. assertThat(dtoAsString, containsString(“booleanValue”));
13. assertThat(dtoAsString, not(containsString(“stringValue”)));
14. }
56
4. Conclusion
The implementation of all these examples and code snippets can be found
in my Github project.
57
5: Jackson – Change Name of Field
58
1. Overview
This quick chapter illustrates how to change the name of a field to map to
another JSON property on serialization.
59
2. Change Name of Field for Serialization
1. {“stringValue”:”some value”}
1. @JsonProperty(“strVal”)
2. public String getStringValue() {
3. return stringValue;
4. }
1. {“strVal”:”some value”}
60
A simple unit test should verify the output is correct:
1. @Test
2. public void givenNameOfFieldIsChanged_whenSerializing_
3. thenCorrect()
4. throws JsonParseException, IOException {
5. ObjectMapper mapper = new ObjectMapper();
6. MyDtoFieldNameChanged dtoObject = new
7. MyDtoFieldNameChanged();
8. dtoObject.setStringValue(“a”);
9.
10. String dtoAsString = mapper.writeValueAsString(dtoObject);
11.
12. assertThat(dtoAsString, not(containsString(“stringValue”)));
13. assertThat(dtoAsString, containsString(“strVal”));
14. }
61
3. Conclusion
The implementation of all these examples and code snippets can be found
in my Github project.
62
6: Jackson Unmarshalling JSON with Unknown
Properties
63
1. Overview
In this chapter, we’re going to take a look at the unmarshalling process with
Jackson 2.x – specifically at how to deal with JSON content with unknown
properties.
64
2. Unmarshall a JSON with Additional/Unknown Fields
JSON input comes in all shapes and sizes – and most of the time, we need to
map it to predefined Java objects with a set number of fields. The goal is to
simply ignore any JSON properties that cannot be mapped to an existing
Java field.
For example, say we need to unmarshal JSON to the following Java entity:
1. @Test(expected = UnrecognizedPropertyException.class)
2. public void givenJsonHasUnknownValues_whenDeserializing_
3. thenException()
4. throws JsonParseException, JsonMappingException, IOException {
5. String jsonAsString =
6. “{“stringValue”:”a”,” +
7. “”intValue”:1,” +
8. “”booleanValue”:true,” +
9. “”stringValue2”:”something”}”;
10. ObjectMapper mapper = new ObjectMapper();
11.
12. MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
13.
14. assertNotNull(readValue);
15. }
65
This will fail with the following exception:
1. com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
2. Unrecognized field “stringValue2” (class org.baeldung.jackson.
3. ignore.MyDto),
4. not marked as ignorable (3 known properties: “stringValue”,
5. “booleanValue”, “intValue”])
1. new ObjectMapper()
2. .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
3. false)
We should then be able to read this kind of JSON into a predefined Java
entity:
1. @Test
2. public void givenJsonHasUnknownValuesButJacksonIsIgnoringUnknowns_
3. whenDeserializing_thenCorrect()
4. throws JsonParseException, JsonMappingException, IOException {
5.
6. String jsonAsString =
7. “{“stringValue”:”a”,” +
8. “”intValue”:1,” +
9. “”booleanValue”:true,” +
10. “”stringValue2”:”something”}”;
11. ObjectMapper mapper = new ObjectMapper()
12. .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
13. false);
14.
15. MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
16.
17. assertNotNull(readValue);
18. assertThat(readValue.getStringValue(), equalTo(“a”));
19. assertThat(readValue.isBooleanValue(), equalTo(true));
20. assertThat(readValue.getIntValue(), equalTo(1));
21. }
66
2.3. Dealing with Unknown Fields on the Class
1. @JsonIgnoreProperties(ignoreUnknown = true)
2. public class MyDtoIgnoreUnknown { ... }
1. @Test
2. public void givenJsonHasUnknownValuesButIgnoredOnClass_
3. whenDeserializing_thenCorrect()
4. throws JsonParseException, JsonMappingException, IOException {
5. String jsonAsString =
6. “{“stringValue”:”a”,” +
7. “”intValue”:1,” +
8. “”booleanValue”:true,” +
9. “”stringValue2”:”something”}”;
10. ObjectMapper mapper = new ObjectMapper();
11. MyDtoIgnoreUnknown readValue = mapper
12. .readValue(jsonAsString, MyDtoIgnoreUnknown.class);
13. assertNotNull(readValue);
14. assertThat(readValue.getStringValue(), equalTo(“a”));
15. assertThat(readValue.isBooleanValue(), equalTo(true));
16. assertThat(readValue.getIntValue(), equalTo(1));
17. }
1. @Test
2. public void givenNotAllFieldsHaveValuesInJson_
3. whenDeserializingAJsonToAClass_thenCorrect()
4. throws JsonParseException, JsonMappingException, IOException {
5. String jsonAsString =
6. “{“stringValue”:”a”,”booleanValue”:true}”;
7. ObjectMapper mapper = new ObjectMapper();
8. MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
9. assertNotNull(readValue);
10. assertThat(readValue.getStringValue(), equalTo(“a”));
11. assertThat(readValue.isBooleanValue(), equalTo(true));
12. }
67
4. Conclusion
This is one of the most common things to configure when working with
Jackson since it’s often the case we need to map JSON results of external
REST APIs to an internal Java representation of the entities of the API.
The implementation of all these examples and code snippets can be found
in my Github project.
68