Do JSON With Jackson by Baeldung
Do JSON With Jackson by Baeldung
JSON
Jackson
with
By Baeldung
Table Of Contents
1: A Guide to Jackson Annotations
2: Jackson Ignore Properties on Marshalling
3: Ignore Null Fields with Jackson
4: Jackson Change Name of Field
5: Jackson Marshall String to JsonNode
6: Jackson Unmarshalling JSON with Unknown
Properties
Page 2 / 64
Introduction........... 7
7
7
2.2. @JsonGetter 9
2.3. @JsonPropertyOrder 10
2.4. @JsonRawValue
11
2.5. @JsonValue. 12
2.6. @JsonRootName
12
2.7. @JsonSerialize 14
3. Jackson Deserialization Annotations
15
3.1. @JsonCreator 15
3.2. @JacksonInject
16
3.3. @JsonAnySetter
17
3.4. @JsonSetter 19
3.5. @JsonDeserialize
20
21
21
23
Page 3 / 64
4.5. @JsonAutoDetect
24
25
27
6.1. @JsonProperty 27
6.2. @JsonFormat 29
6.3. @JsonUnwrapped
30
33
6.7. @JsonFilter.35
7. Custom Jackson Annotation
36
37
38
41
42
Page 4 / 64
47
48
4. Conclusion........ 49
56
5. Conclusion........ 57
Page 5 / 64
60
61
63
4. Conclusion........ 63
Page 6 / 64
Chapter
1
Introduction
This short and practical eBook is focused on the basics of Jackson and on getting JSON
serialized and deserialized efficiently and with flexibility.
1: A Guide to Jackson
Annotations
1. Overview
In this section well do a deep dive into Jackson Annotations.
Well see how to use the existing annotations, how to create custom ones and finally how to
disable them.
2.1. @JsonAnyGetter
The @JsonAnyGetter annotation allows the flexibility of using a Map field as standard
properties.
Page 8 / 64
Heres a quick example the ExtendableBean entity has the name property and a set of
extendable attributes in form of key/value pairs:
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
When we serialize an instance of this entity, we get all the key-values in the Map as standard,
plain properties:
name:My bean,
attr2:val2,
attr1:val1
And here how the serialization of this entity looks like in practice:
@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
throws JsonProcessingException {
ExtendableBean bean = new ExtendableBean(My bean);
bean.add(attr1, val1);
bean.add(attr2, val2);
Page 9 / 64
2.2. @JsonGetter
The @JsonGetter annotation is an alternative to @JsonProperty annotation to mark the
specified method as a getter method.
In the following example we specify the method getTheName() as the getter method of
name property of MyBean entity:
@JsonGetter(name)
public String getTheName() {
return name;
}
@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, My bean);
Page 10 / 64
2.3. @JsonPropertyOrder
The @JsonPropertyOrder annotation is used to specify the order of properties on serialization.
Lets set a custom order for the properties of a MyBean entity:
@JsonPropertyOrder({ name, id })
public class MyBean {
public int id;
public String name;
}
{
}
name:My bean,
id:1
@Test
public void whenSerializingUsingJsonPropertyOrder_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, My bean);
Page 11 / 64
2.4. @JsonRawValue
@JsonRawValue is used to instruct the Jackson to serialize a property exactly as is.
In the following example we use @JsonRawValue to embed some custom JSON as value of
an entity:
@JsonRawValue
public String json;
name:My bean,
json:{
attr:false
}
@Test
public void whenSerializingUsingJsonRawValue_thenCorrect()
throws JsonProcessingException {
RawBean bean = new RawBean(My bean, {attr:false});
Page 12 / 64
2.5. @JsonValue
@JsonValue indicates a single method that should be used to serialize the entire instance.
For example in an enum we annotate the getName with @JsonValue so that any such entity
is serialized via its name:
@JsonValue
public String getName() {
return name;
}
Our test:
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
throws JsonParseException, IOException {
String enumAsString =
new ObjectMapper().writeValueAsString(TypeEnumWithValue.TYPE1);
}
2.6. @JsonRootName
The @JsonRootName annotation is used if wrapping is enabled to specify the name of the
root wrapper to be used.
Page 13 / 64
{
}
id: 1,
name: John
User: {
id: 1,
name: John
}
So, lets look at an example were going to use the @JsonRootName annotation to indicate
the name of this potential wrapper entity:
@JsonRootName(value = user)
public class UserWithRoot {
public int id;
public String name;
}
By default, the name of the wrapper would be the name of the class UserWithRoot. By using
the annotation, we get the cleaner looking user:
@Test
public void whenSerializingUsingJsonRootName_thenCorrect()
throws JsonProcessingException {
UserWithRoot user = new User(1, John);
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
String result = mapper.writeValueAsString(user);
assertThat(result, containsString(John));
assertThat(result, containsString(user));
Page 14 / 64
user:{
id:1,
name:John
}
2.7. @JsonSerialize
@JsonSerialize is used to indicate a custom serializer will be used to marshall the entity.
Lets look at a quick example were going to use @JsonSerialize to serialize the eventDate
property with a CustomDateSerializer:
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
Page 15 / 64
@Test
public void whenSerializingUsingJsonSerialize_thenCorrect()
throws JsonProcessingException, ParseException {
SimpleDateFormat df = new SimpleDateFormat(dd-MM-yyyy hh:mm:ss);
String toParse = 20-12-2014 02:30:00;
Date date = df.parse(toParse);
Event event = new Event(party, date);
3.1. @JsonCreator
The @JsonCreator annotation is used to tune the constructor/factory used in deserialization.
Its very helpful when we need to deserialize some JSON that doesnt exactly match the
target entity we need to get.
Lets look at an example; say we need to deserialize the following JSON:
{
}
id:1,
theName:My bean
Page 16 / 64
However, there is no theName field in our target entity there is only a name field. Now
we dont want to change the entity itself we just need a little more control over the
unmarshalling process by annotating the constructor with @JsonCreator and using the @
JsonProperty annotation as well:
@JsonCreator
public BeanWithCreator(
@JsonProperty(id) int id,
@JsonProperty(theName) String name) {
this.id = id;
this.name = name;
}
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws JsonProcessingException, IOException {
String json = {id:1,theName:My bean};
BeanWithCreator bean =
new ObjectMapper().reader(BeanWithCreator.class).readValue(json);
assertEquals(My bean, bean.name);
3.2. @JacksonInject
@JacksonInject is used to indicate a property that will get its value from injection and not
from the JSON data.
Page 17 / 64
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws JsonProcessingException, IOException {
String json = {name:My bean};
InjectableValues inject = new InjectableValues.Std().addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
3.3. @JsonAnySetter
@JsonAnySetter allows you the flexibility of using a Map as standard properties. On deserialization, the properties from JSON will simply be added to the map.
Page 18 / 64
Lets see how this works well use @JsonAnySetter to deserialize the entity ExtendableBean:
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
name:My bean,
attr2:val2,
attr1:val1
@Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
throws JsonProcessingException, IOException {
String json = {name:My bean,attr2:val2,attr1:val1};
ExtendableBean bean =
new ObjectMapper().reader(ExtendableBean.class).readValue(json);
Page 19 / 64
3.4. @JsonSetter
@JsonSetter is an alternative to @JsonProperty used to mark the a method as a setter
method.
This is super useful when we need to read some JSON data but the target entity class doesnt
exactly match that data and so we need to tune the process to make it fit.
In the following example, well specify the method setTheName() as the setter of the name
property in our MyBean entity:
@JsonSetter(name)
public void setTheName(String name) {
this.name = name;
}
Now, when we need to unmarshall some JSON data this works perfectly well:
@Test
public void whenDeserializingUsingJsonSetter_thenCorrect()
throws JsonProcessingException, IOException {
String json = {id:1,name:My bean};
MyBean bean =
new ObjectMapper().reader(MyBean.class).readValue(json);
assertEquals(My bean, bean.getTheName());
Page 20 / 64
3.5. @JsonDeserialize
@JsonDeserialize is used to indicate the use of a custom deserializer.
Lets see how that plays out well use @JsonDeserialize to deserialize the eventDate
property with the CustomDateDeserializer:
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
@Override
public Date deserialize(JsonParser jsonparser, DeserializationContext context)
throws IOException, JsonProcessingException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
Page 21 / 64
@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
throws JsonProcessingException, IOException {
String json = {name:party,eventDate:20-12-2014 02:30:00};
SimpleDateFormat df = new SimpleDateFormat(dd-MM-yyyy hh:mm:ss);
Event event = new ObjectMapper().reader(Event.class).readValue(json);
}
@JsonIgnoreProperties({ id })
public class BeanWithIgnore {
public int id;
public String name;
}
Page 22 / 64
@Test
public void whenSerializingUsingJsonIgnoreProperties_thenCorrect()
throws JsonProcessingException, IOException {
BeanWithIgnore bean = new BeanWithIgnore(1, My bean);
String result = new ObjectMapper().writeValueAsString(bean);
4.2. @JsonIgnore
The @JsonIgnore annotation is used to mark a property to be ignored at the field level.
Lets use @JsonIgnore to ignore the property id from serialization:
@Test
public void whenSerializingUsingJsonIgnore_thenCorrect()
throws JsonProcessingException, IOException {
BeanWithIgnore bean = new BeanWithIgnore(1, My bean);
String result = new ObjectMapper().writeValueAsString(bean);
Page 23 / 64
4.3. @JsonIgnoreType
@JsonIgnoreType is used to mark all properties of annotated type to be ignored.
Lets use the annotation to mark all properties of type Name to be ignored:
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
Heres the simple test making sure the ignore works correctly:
@Test
public void whenSerializingUsingJsonIgnoreType_thenCorrect()
throws JsonProcessingException, ParseException {
User.Name name = new User.Name(John, Doe);
User user = new User(1, name);
String result = new ObjectMapper().writeValueAsString(user);
assertThat(result, containsString(1));
assertThat(result, not(containsString(name)));
assertThat(result, not(containsString(John)));
Page 24 / 64
4.4. @JsonInclude
@JsonInclude is used to exclude properties with empty/null/default values.
Lets look at an example excluding nulls from serialization:
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
assertThat(result, containsString(1));
assertThat(result, not(containsString(name)));
4.5. @JsonAutoDetect
@JsonAutoDetect is used to override the default semantics of which properties are visible and
which are not.
Lets take a look at how the annotation can be very helpful with a simple example lets enable
serializing private properties:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}
Page 25 / 64
@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
throws JsonProcessingException, IOException {
PrivateBean bean = new PrivateBean(1, My bean);
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString(1));
assertThat(result, containsString(My bean));
Page 26 / 64
@JsonTypeName(dog)
public static class Dog extends Animal {
public double barkVolume;
}
@JsonTypeName(cat)
public static class Cat extends Animal {
boolean likesCream;
public int lives;
}
When we do serialization:
@Test
public void whenSerializingPolymorphic_thenCorrect()
throws JsonProcessingException, IOException {
Zoo.Dog dog = new Zoo.Dog(lacy);
Zoo zoo = new Zoo(dog);
String result = new ObjectMapper().writeValueAsString(zoo);
assertThat(result, containsString(type));
assertThat(result, containsString(dog));
Heres what serializing the Zoo instance with the Dog will result in:
animal: {
type: dog,
name: lacy,
barkVolume: 0
}
Page 27 / 64
Now for de-serialization lets start from the following JSON input:
animal:{
name:lacy,
type:cat
}
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws JsonProcessingException, IOException {
String json = {animal:{name:lacy,type:cat}};
Zoo zoo = new ObjectMapper().reader()
.withType(Zoo.class)
.readValue(json);
assertEquals(lacy, zoo.animal.name);
assertEquals(Zoo.Cat.class, zoo.animal.getClass());
6.1. @JsonProperty
@JsonProperty is used to indicate the property name in JSON.
Lets go over the annotation with a simple example and use @JsonProperty to serialize/
Page 28 / 64
desrialize the property name when were dealing with non-standard getters and setters:
@JsonProperty(name)
public String getTheName() {
return name;
}
Our test:
@Test
public void whenUsingJsonProperty_thenCorrect()
throws IOException {
MyBean bean = new MyBean(1, My bean);
String result = new ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString(My bean));
assertThat(result, containsString(1));
Page 29 / 64
6.2. @JsonFormat
The @JsonFormat annotation can be used to specify a format when serializing Date/Time
values.
In the following example we use @JsonFormat to control the format of the property
eventDate:
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = dd-MM-yyyy hh:mm:ss)
public Date eventDate;
@Test
public void whenSerializingUsingJsonFormat_thenCorrect()
throws JsonProcessingException, ParseException {
SimpleDateFormat df = new SimpleDateFormat(dd-MM-yyyy hh:mm:ss);
df.setTimeZone(TimeZone.getTimeZone(UTC));
String toParse = 20-12-2014 02:30:00;
Date date = df.parse(toParse);
Event event = new Event(party, date);
String result = new ObjectMapper().writeValueAsString(event);
}
assertThat(result, containsString(toParse));
Page 30 / 64
6.3. @JsonUnwrapped
@JsonUnwrapped is used to define that a value should be unwrapped / flattened when
serialized.
Lets see exactly how that works; well use the annotation to unwrap the property name:
@Test
public void whenSerializingUsingJsonUnwrapped_thenCorrect()
throws JsonProcessingException, ParseException {
UnwrappedUser.Name name = new UnwrappedUser.Name(John, Doe);
UnwrappedUser user = new UnwrappedUser(1, name);
String result = new ObjectMapper().writeValueAsString(user);
assertThat(result, containsString(John));
assertThat(result, not(containsString(name)));
Page 31 / 64
Heres how the output looks like the fields of the static nested class unwrapped along with the
other field:
id:1,
firstName:John,
lastName:Doe
6.4. @JsonView
@JsonView is used to indicate the View in which the property will be included for serialization/
deserialization.
An example will show exactly how that works well use @JsonView to serialize an instance of
Item entity.
Lets start with the views:
@JsonView(Views.Internal.class)
public String ownerName;
Page 32 / 64
@Test
public void whenSerializingUsingJsonView_thenCorrect()
throws JsonProcessingException {
Item item = new Item(2, book, John);
String result = new ObjectMapper().writerWithView(Views.Public.class)
.writeValueAsString(item);
assertThat(result, containsString(book));
assertThat(result, containsString(2));
assertThat(result, not(containsString(John)));
@JsonManagedReference
public UserWithRef owner;
@JsonBackReference
public List<ItemWithRef> userItems;
Page 33 / 64
@Test
public void whenSerializingUsingJacksonReferenceAnnotation_thenCorrect()
throws JsonProcessingException {
UserWithRef user = new UserWithRef(1, John);
ItemWithRef item = new ItemWithRef(2, book, user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString(book));
assertThat(result, containsString(John));
assertThat(result, not(containsString(userItems)));
6.6. @JsonIdentityInfo
@JsonIdentityInfo is used to indicate that Object Identity is to be used when serializing/
deserializing values for instance to deal with infinite recursion type of problems.
In the following example we have an ItemWithIdentity entity with a bidirectional realtionship
with the UserWithIdentity entity:
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = id)
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
Page 34 / 64
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = id)
public class UserWithIdentity {
public int id;
public String name;
public List<ItemWithIdentity> userItems;
}
@Test
public void whenSerializingUsingJsonIdentityInfo_thenCorrect()
throws JsonProcessingException {
UserWithIdentity user = new UserWithIdentity(1, John);
ItemWithIdentity item = new ItemWithIdentity(2, book, user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString(book));
assertThat(result, containsString(John));
assertThat(result, containsString(userItems));
id: 2,
itemName: book,
owner: {
id: 1,
name: John,
userItems: [
2
]
}
Page 35 / 64
6.7. @JsonFilter
The @JsonFilter annotation specifies a filter to be used during serialization.
Lets take a look at an example; first, we define the entity and we point to the filter:
@JsonFilter(myFilter)
public class BeanWithFilter {
public int id;
public String name;
}
Now, in the full test, we define the filter which excludes all other properties except name from
serialization:
@Test
public void whenSerializingUsingJsonFilter_thenCorrect()
throws JsonProcessingException {
BeanWithFilter bean = new BeanWithFilter(1, My bean);
FilterProvider filters =
new SimpleFilterProvider().addFilter(myFilter,
SimpleBeanPropertyFilter.filterOutAllExcept(name));
String result = new ObjectMapper().writer(filters)
.writeValueAsString(bean);
Page 36 / 64
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ name, id, dateCreated })
public @interface CustomAnnotation {}
@CustomAnnotation
public class BeanWithCustomAnnotation {
public int id;
public String name;
public Date dateCreated;
}
We can see how it does combine the existing annotations into a simpler, custom one that we
can use as a shorthand:
@Test
public void whenSerializingUsingCustomAnnotation_thenCorrect()
throws JsonProcessingException {
BeanWithCustomAnnotation bean =
new BeanWithCustomAnnotation(1, My bean, null);
String result = new ObjectMapper().writeValueAsString(bean);
Page 37 / 64
{
}
name:My bean,
id:1
@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect()
throws JsonProcessingException {
User user = new User(1, John);
String result = new ObjectMapper().writeValueAsString(user);
assertThat(result, containsString(John));
Page 38 / 64
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ name, id })
public class MyBean {
public int id;
public String name;
}
Now, after disabling annotations, these should have no effect and the defaults of the library
should apply:
@Test
public void whenDisablingAllAnnotations_thenAllDisabled()
throws JsonProcessingException, IOException {
MyBean bean = new MyBean(1, null);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
String result = mapper.writeValueAsString(bean);
assertThat(result, containsString(1));
assertThat(result, containsString(name));
{id:1}
Page 39 / 64
{
}
id:1,
name:null
10. Conclusion
This section has been a deep-dive into Jackson annotations,
just scratching the surface of the kind of flexibility you can get
using them properly.
Page 40 / 64
Chapter
2
2: Jackson Ignore
Properties on Marshalling
1. Overview
This section 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 arent enough and we need to control exactly what
gets serialized to JSON and there are several ways to ignore properties.
@JsonIgnoreProperties(value = { intValue })
public class MyDto {
private String stringValue;
private int intValue;
private boolean booleanValue;
public MyDto() {
super();
}
}
We can now test that, after the object is written to json, the field is indeed not part of the
output:
@Test
public void givenFieldIsIgnoredByName_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
}
assertThat(dtoAsString, not(containsString(intValue)));
Page 43 / 64
We can now test that the intValue field is indeed not part of the serialized json output:
@Test
public void givenFieldIsIgnoredDirectly_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
}
assertThat(dtoAsString, not(containsString(intValue)));
@JsonIgnoreType
public class SomeType { ... }
More often than not however, we dont 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 wed like to ignore, and annotate that with @
JsonIgnoreType instead:
@JsonIgnoreType
public class MyMixInForString {
//
}
Then we register that mixin to replace (and ignore) all String types during marshalling:
mapper.addMixInAnnotations(String.class, MyMixInForString.class);
Page 44 / 64
@Test
public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(String.class, MyMixInForString.class);
MyDto dtoObject = new MyDto();
dtoObject.setBooleanValue(true);
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, containsString(intValue));
assertThat(dtoAsString, containsString(booleanValue));
assertThat(dtoAsString, not(containsString(stringValue)));
@JsonFilter(myFilter)
public class MyDtoWithFilter { ... }
Then, we define a simple filter that will ignore the intValue field:
Page 45 / 64
Now we can serialize the object and make sure that the intValue field is not present in the
JSON output:
@Test
public final void givenTypeHasFilterThatIgnoresFieldByName_whenDtoIsSerialized_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept(intValue);
FilterProvider filters = new SimpleFilterProvider().addFilter(myFilter, theFilter);
MyDtoWithFilter dtoObject = new MyDtoWithFilter();
String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);
assertThat(dtoAsString, not(containsString(intValue)));
assertThat(dtoAsString, containsString(booleanValue));
assertThat(dtoAsString, containsString(stringValue));
System.out.println(dtoAsString);
6. Conclusion
The section illustrated how to ignore fields on serialization
first by name, then directly, and finally we ignored the entire
java type with MixIns and we use filters for more control of the
output.
Chapter
3
@JsonInclude(Include.NON_NULL)
public class MyDto { ... }
Or more granularity at the field level:
Page 48 / 64
Now, we should be able to test that null values are indeed not part of the final JSON output:
@Test
public void givenNullsIgnoredOnClass_whenWritingObjectWithNullField_thenIgnored()
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, containsString(intValue));
assertThat(dtoAsString, not(containsString(stringValue)));
mapper.setSerializationInclusion(Include.NON_NULL);
Now any null field in any class serialized through this mapper is going to be ignored:
@Test
public void givenNullsIgnoredGlobally_whenWritingObjectWithNullField_thenIgnored()
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
MyDto dtoObject = new MyDto();
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, containsString(intValue));
assertThat(dtoAsString, containsString(booleanValue));
assertThat(dtoAsString, not(containsString(stringValue)));
Page 49 / 64
4. Conclusion
Ignoring null fields is such a common Jackson configuration
because its often the case that we need to have better
control over the JSON output. This section shows how to do
that for classes there are however more advanced use-cases.
Page 50 / 64
Chapter
4
Page 52 / 64
{stringValue:some value}
To customize that output so that, instead of stringValue we get for example strValue, we
need to simply annotate the getter:
@JsonProperty(strVal)
public String getStringValue() {
return stringValue;
}
Now, on serialization, we will get the desired output:
{strValue:some value}
A simple unit test should verify the output is correct:
@Test
public void givenNameOfFieldIsChanged_whenSerializing_thenCorrect()
throws JsonParseException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyDtoFieldNameChanged dtoObject = new MyDtoFieldNameChanged();
dtoObject.setStringValue(a);
String dtoAsString = mapper.writeValueAsString(dtoObject);
assertThat(dtoAsString, not(containsString(stringValue)));
assertThat(dtoAsString, containsString(strVal));
Page 53 / 64
3. Conclusion
Marshalling an entity to adhere to a specific JSON format is a
common task and this section shows how to do is simply by
using the @JsonProperty annotation.
Page 54 / 64
Chapter
5
5: Jackson Marshall
String to JsonNode
1. Overview
This quick section will show how to use Jackson 2 to convert a JSON String to a JsonNode
(com.fasterxml.jackson.databind.JsonNode).
2. Quick Parsing
Very simply, to parse the JSON String we only need an ObjectMapper:
@Test
public void whenParsingJsonStringIntoJsonNode_thenCorrect()
throws JsonParseException, IOException {
String jsonString = {k1:v1,k2:v2};
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonString);
}
assertNotNull(actualObj);
Page 56 / 64
@Test
public void givenUsingLowLevelApi_whenParsingJsonStringIntoJsonNode_thenCorrect()
throws JsonParseException, IOException {
String jsonString = {k1:v1,k2:v2};
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getFactory();
JsonParser parser = factory.createParser(jsonString);
JsonNode actualObj = mapper.readTree(parser);
}
assertNotNull(actualObj);
@Test
public void givenTheJsonNode_whenRetrievingDataFromId_thenCorrect()
throws JsonParseException, IOException {
String jsonString = {k1:v1,k2:v2};
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonString);
// When
JsonNode jsonNode1 = actualObj.get(k1);
assertThat(jsonNode1.textValue(), equalTo(v1));
Page 57 / 64
5. Conclusion
This section illustrated how to parse JSON Strings into the
Jackson JsonNode model to enable a structured processing of
the JSON Object.
Page 58 / 64
Chapter
6
6:JacksonUnmarshallingJSONwithUnknownProperties
6: Jackson Unmarshalling
JSON with Unknown
Properties
1. Overview
In this section, were going to take a look at the unmarshalling process with Jackson 2.x
specifically at how to deal with JSONs with unknown properties.
Page 60 / 64
6:JacksonUnmarshallingJSONwithUnknownProperties
For example, say we need to unmarshall JSON to the following java entity:
@Test(expected = UnrecognizedPropertyException.class)
public void givenJsonHasUnknownValues_whenDeserializing_thenException()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
{stringValue:a, +
intValue:1, +
booleanValue:true, +
stringValue2:something};
ObjectMapper mapper = new ObjectMapper();
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
}
assertNotNull(readValue);
Page 61 / 64
6:JacksonUnmarshallingJSONwithUnknownProperties
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field stringValue2 (class org.baeldung.jackson.ignore.MyDto),
not marked as ignorable (3 known properties: stringValue, booleanValue, intValue])
We should then be able to read this kind of JSON into a predefined java entity:
@Test
public void
givenJsonHasUnknownValuesButJacksonIsIgnoringUnknowns_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
{stringValue:a, +
intValue:1, +
booleanValue:true, +
stringValue2:something};
ObjectMapper mapper =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo(a));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
Page 62 / 64
6:JacksonUnmarshallingJSONwithUnknownProperties
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyDtoIgnoreUnknown { ... }
Now, we should be able to test the same behavior as before unknown fields are simply
ignored and only known fields are mapped:
@Test
public void givenJsonHasUnknownValuesButIgnoredOnClass_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
{stringValue:a, +
intValue:1, +
booleanValue:true, +
stringValue2:something};
ObjectMapper mapper = new ObjectMapper();
MyDtoIgnoreUnknown readValue = mapper.readValue(jsonAsString, MyDtoIgnoreUnknown.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo(a));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
Page 63 / 64
6:JacksonUnmarshallingJSONwithUnknownProperties
@Test
public void givenNotAllFieldsHaveValuesInJson_whenDeserializingAJsonToAClass_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString = {stringValue:a,booleanValue:true};
ObjectMapper mapper = new ObjectMapper();
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo(a));
assertThat(readValue.isBooleanValue(), equalTo(true));
4. Conclusion
This section covered deserializing a JSON with additional,
unknown properties, using Jackson. This is one of the most
common things to configure when working with Jackson,
since its often the case to map JSONs of external REST APIs
to an internal java representation of the entities of the API.
Page 64 / 64