К оглавлению Jackson.
1. Обзор
В этой статье мы рассмотрим аннотации Jackson.
Мы изучим как использовать существующие аннотации Jackson и как создать свои.
А также как их отключить.
2. Аннотации Jackson для сериализации
Для начала рассмотрим аннотации применяемые для сериализации объектов.
2.1 @JsonAnyGetter
Аннотация @JsonAnyGetter позволяет сериализовать Map как обычные свойства класса, без вложенности.
Пример — класс ExtendableBean имеет фиксированное свойство name и поле с типом Map для задания произвольного количества атрибутов в виде пар key/value:
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
}
Сериализация без аннотации @JsonAnyGetter:
{
"name": "BeanName",
"properties": {
"attr2": "value2",
"attr1": "value1"
}
}
С аннотацией @JsonAnyGetter Jackson сериализует атрибуты key-value как обычные свойствами объекта, без вложенности:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
2.2. @JsonGetter
Аннотация @JsonGetter (альтернатива аннотации @JsonProperty), которой можно пометить определённый метод как геттер.
В следующем примере помечаем разные методы класса original siteelf bar 600 vapetelefoonhoesjes se 2020www.adiuc.org/MyBean аннотациями @JsonGetter :
public class MyBean {
private int id;
private String name;
// свойство name существует
@JsonGetter("name")
public String getTheName() {
return name;
}
// название метода без get...
@JsonGetter
public String testMethod1() {
return "testMethod1";
}
// название метода с get...
@JsonGetter
public String getTestMethod2() {
return "getTestMethod2";
}
// // свойство myProperty не существует
@JsonGetter("myProperty")
public String testMethod3() {
return "testMethod3";
}
}
Результат сериализации:
{
"name": "BeanName", // getTheName --> name
"testMethod1": "testMethod1",
"testMethod2": "getTestMethod2", // getTestMethod2 --> testMethod2
"myProperty": "testMethod3" // testMethod3 --> myProperty
}
2.3. @JsonPropertyOrder
Аннотация @JsonPropertyOrder используется для указания порядка свойств при сериализации объекта в JSON.
Давайте зададим свой порядок свойств класса MyBean:
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
Результат сериализации:
{
"name":"My bean",
"id":1
}
2.4. @JsonRawValue
@JsonRawValue используется чтобы Jackson сериализовал свойство так как оно есть.
Пример:
public class RawBean {
public String name;
@JsonRawValue
public String json;
}
Результат сериализации:
{
"name":"My bean",
"json":{
"attr":false
}
}
2.5. @JsonValue
@JsonValue указывает на то что результат вызова метода должен использоваться как сериализация всего экземпляра класса.
Например для перечислений – мы помечаем метод getName аннотацией @JsonValue таким образом, что элементы перечисления сериализуются через значение свойства name:
public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
TypeEnumWithValue(Integer id, String name) {
this.id = id;
this.name = name;
}
@JsonValue
public String getName() {
return name;
}
}
Результат:
// "TYPE1" - без @JsonValue
// "Type A" - с @JsonValue
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
throws JsonParseException, IOException {
String enumAsString = new ObjectMapper()
.writeValueAsString(TypeEnumWithValue.TYPE1); // "Type A"
assertThat(enumAsString, is("\"Type A\""));
}
2.6. @JsonRootName
Аннотация @JsonRootName используется, если включена вложенность (wrapping), для указания названия корневого элемента.
Защитите свой телефон стильно с помощью нашего премиум telefoonhoesje коллекция. Наши стильные дизайны не только защищают ваше устройство от ежедневного износа, но и повышают его эстетическую привлекательность. Выбирайте из множества цветов и материалов, чтобы найти идеальное соответствие вашей индивидуальности. С нашими telefoonhoesjes вы можете наслаждаться спокойствием, зная, что ваш смартфон надежно защищен и выглядит великолепно. Улучшите внешний вид вашего телефона сегодня!Вложенность означает, что при сериализации класса User вместо этого:
{
"id": 1,
"name": "John"
}
получим вот это:
{
"User": {
"id": 1,
"name": "John"
}
}
Чтобы изменить название корневого элемента на «user» применим аннотацию @JsonRootName :
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
По-умолчанию, названием корневого элемента будет название класса – UserWithRoot. Используя данную аннотацию, мы получим более удобное название — 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"));
}
Результат сериализации:
{
"user":{
"id":1,
"name":"John"
}
}
2.7. @JsonSerialize
@JsonSerialize применяется для указания класса, с помощью которого будет производиться сериализация сущности.
Рассмотрим пример – применим аннотацию @JsonSerialize для сериализации свойства eventDate с помощь класса CustomDateSerializer:
public class Event {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
Код простого кастомного сериализации Jackson:
public class CustomDateSerializer extends StdSerializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize(
Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}
Код тестирования:
@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);
String result = new ObjectMapper().writeValueAsString(event);
assertThat(result, containsString(toParse));
}
3. Jackson Deserialization Annotations
Далее рассмотрим аннотации Jackson для десериализации, т.е. для обратного преобразования JSON в Java-объект.
3.1. @JsonCreator
Аннотация @JsonCreator используется для настройки конструктора или фабрики, которые будут применяться при десериализации.
Это очень полезно когда нам нужно десериализовать некий JSON, который не в полной мере соответствует десериализуемому объекту.
Тут пригодится пример. Скажем, нам нужно десериализовать следующий JSON:
{
"id":1,
"theName":"My bean"
}
Однако, в нашем целевом классе нет поля theName – в нём есть только поле name. При этом мы не хотим менять наш класс. Мы можем указать Jackson, как нужно десериализовывать наш класс, отметив конструктор аннотацией @JsonCreator и используя @JsonProperty для аргументов:
public class BeanWithCreator {
public int id;
public String name;
@JsonCreator
public BeanWithCreator(
@JsonProperty("id") int id,
@JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
Тестирование:
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"theName\":\"My bean\"}";
BeanWithCreator bean = new ObjectMapper()
.readerFor(BeanWithCreator.class)
.readValue(json);
assertEquals("My bean", bean.name);
}
3.2. @JacksonInject
@JacksonInject используется чтобы пометить поле, в которое нужно внедрить значение, а не брать из данных JSON. При этом внедрение можно выполнить как по типу данных, так и по названию свойства.
В ниже приведённом примере мы используем @JacksonInject для внедрения своего значения в свойство id:
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
}
Обратите внимание, что в JSON нет значения для id, однако в десериализованном объекте оно уже есть:
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws 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);
assertEquals("My bean", bean.name);
assertEquals(1, bean.id);
}
3.3. @JsonAnySetter
@JsonAnySetter помечается метод, в который будут передаваться все нераспознанные поля и их значения. Помеченный метод должен иметь определенную сигнатуру. Таким образом можно складывать значение в Map.
Применим @JsonAnySetter для десериализации объектаExtendableBean:
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
JSON для десериализации:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
Поле name попадёт в свойство name, а поля attr1 и attr2 попадут в метод add, т.к. в классе нет соответствующих свойств attr1, attr2.
Проверка:
@Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
throws IOException {
String json
= "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";
ExtendableBean bean = new ObjectMapper()
.readerFor(ExtendableBean.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals("val2", bean.getProperties().get("attr2"));
}
3.4. @JsonSetter
@JsonSetter это альтернатива @JsonProperty – применяется для обозначения метода, который будет использоваться для установки значения свойству (сеттер).
Это очень полезно когда данные из JSON не совсем подходят под целевой класс или с данными нужно выполнить какие-то простые проверки или преобразования.
В следующем примере у нас есть метод setTheName() как сеттер свойства name в классе MyBean:
public class MyBean {
public int id;
private String name;
@JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
Метод setTheName() будет использоваться для десериализации свойства name:
@Test
public void whenDeserializingUsingJsonSetter_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"name\":\"My bean\"}";
MyBean bean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(json);
assertEquals("My bean", bean.getTheName());
}
3.5. @JsonDeserialize
@JsonDeserialize используется для указания использовать указанный пользовательский десериализатор.
Пометим свойство eventDate аннотацией @JsonDeserialize для десериализации с помощью класса CustomDateDeserializer:
public class Event {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
Код нашего десериализатора:
public class CustomDateDeserializer
extends StdDeserializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(
JsonParser jsonparser, DeserializationContext context)
throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
Тестирование результата:
@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
throws 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()
.readerFor(Event.class)
.readValue(json);
assertEquals(
"20-12-2014 02:30:00", df.format(event.eventDate));
}
4. Jackson Property Inclusion Annotations
4.1. @JsonIgnoreProperties
@JsonIgnoreProperties – one of the most common annotations in Jackson – is used to mark a property or a list of properties to be ignored at the class level.
Let’s go over a quick example ignoring the property id from serialization:
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
And here’s the test making sure the ignore happens:
@Test
public void whenSerializingUsingJsonIgnoreProperties_thenCorrect()
throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
4.2. @JsonIgnore
The @JsonIgnore annotation is used to mark a property to be ignored at the field level.
Let’s use @JsonIgnore to ignore the property id from serialization:
public class BeanWithIgnore {
@JsonIgnore
public int id;
public String name;
}
And the test making sure that id was successfully ignored:
@Test
public void whenSerializingUsingJsonIgnore_thenCorrect()
throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
4.3. @JsonIgnoreType
@JsonIgnoreType is used to mark all properties of an annotated type to be ignored.
Let’s use the annotation to mark all properties of type Name to be ignored:
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
Here’s 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")));
}
4.4. @JsonInclude
@JsonInclude is used to exclude properties with empty/null/default values.
Let’s look at an example – excluding nulls from serialization:
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
Here’s the full test:
public void whenSerializingUsingJsonInclude_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, null);
String result = new ObjectMapper()
.writeValueAsString(bean);
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.
Let’s take a look at how the annotation can be very helpful with a simple example – let’s enable serializing private properties:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}
And the test:
@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
throws JsonProcessingException {
PrivateBean bean = new PrivateBean(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("1"));
assertThat(result, containsString("My bean"));
}
5. Jackson Polymorphic Type Handling Annotations
Next – let’s take a look at Jackson polymorphic type handling annotations:
- @JsonTypeInfo is used to indicate details of what type information is included in serialization
- @JsonSubTypes is used to indicate sub-types of annotated type
- @JsonTypeName is used to define logical type name to use for annotated class
Let’s look at a more complex example and use all three – @JsonTypeInfo, @JsonSubTypes, and @JsonTypeName – to serialize/deserialize the entity Zoo:
public class Zoo {
public Animal animal;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public static class Animal {
public String name;
}
@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 {
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"));
}
Here’s what serializing the Zoo instance with the Dog will result in:
{
"animal": {
"type": "dog",
"name": "lacy",
"barkVolume": 0
}
}
Now for de-serialization – let’s start with the following JSON input:
{
"animal":{
"name":"lacy",
"type":"cat"
}
}
And let’s see how that gets unmarshalled to a Zoo instance:
6. Jackson General Annotations
Next – let’s discuss some of Jackson more general annotations.
6.1. @JsonProperty
@JsonProperty is used to indicate the property name in JSON.
Let’s go over the annotation with a simple example – and use @JsonProperty to serialize/deserialize the property name when we’re dealing with non-standard getters and setters:
public class MyBean {
public int id;
private String name;
@JsonProperty("name")
public void setTheName(String name) {
this.name = name;
}
@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"));
MyBean resultBean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(result);
assertEquals("My bean", resultBean.getTheName());
}
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:
public class Event {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}
And here’s the test:
@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));
}
6.3. @JsonUnwrapped
@JsonUnwrapped is used for defining values that should be unwrapped/flattened when serialized/deserialized.
Let’s see exactly how that works; we’ll use the annotation to unwrap the property name:
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public static class Name {
public String firstName;
public String lastName;
}
}
Let’s now serialize an instance of this class:
@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")));
}
Here’s 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 – we’ll use @JsonView to serialize an instance of Item entity.
Let’s start with the views:
public class Views {
public static class Public {}
public static class Internal extends Public {}
}
And now here’s the Item entity, using the views:
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
Finally – the full test:
@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")));
}
6.5. @JsonManagedReference, @JsonBackReference
The @JsonManagedReference and @JsonBackReference annotations are used to handle parent/child relationships and work around loops.
In the following example – we use @JsonManagedReference and @JsonBackReference to serialize our ItemWithRef entity:
public class ItemWithRef {
public int id;
public String itemName;
@JsonManagedReference
public UserWithRef owner;
}
Our UserWithRef entity:
public class UserWithRef {
public int id;
public String name;
@JsonBackReference
public List<ItemWithRef> userItems;
}
And the test:
@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 relationship with the UserWithIdentity entity:
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
And the UserWithIdentity entity:
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class UserWithIdentity {
public int id;
public String name;
public List<ItemWithIdentity> userItems;
}
Now, let’s see how the infinite recursion problem is handled:
@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"));
}
Here’s the full output of the serialized item and user:
{
"id": 2,
"itemName": "book",
"owner": {
"id": 1,
"name": "John",
"userItems": [
2
]
}
}
6.7. @JsonFilter
The @JsonFilter annotation specifies a filter to be used during serialization.
Let’s 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);
assertThat(result, containsString("My bean"));
assertThat(result, not(containsString("id")));
}
7. Custom Jackson Annotation
Next – let’s see how to create a custom Jackson annotation; we can make use of the @JacksonAnnotationsInside annotation – as in the following example:
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {
}
Now, if we use the new annotation on an entity:
@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);
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
assertThat(result, not(containsString("dateCreated")));
}
The output of the serialization process:
{
"name":"My bean",
"id":1
}
8. Jackson MixIn Annotations
Next – let’s see how to use Jackson MixIn annotations.
Let’s use the MixIn annotations to – for example – ignore properties of type User:
public class Item {
public int id;
public String itemName;
public User owner;
}
@JsonIgnoreType
public class MyMixInForIgnoreType {
}
Let’s see this in action:
@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect()
throws JsonProcessingException {
Item item = new Item(1, "book", null);
String result = new ObjectMapper().writeValueAsString(item);
assertThat(result, containsString("owner"));
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
result = mapper.writeValueAsString(item);
assertThat(result, not(containsString("owner")));
}
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:
@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 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"));
}
The result of serialization before disabling annotations:
{
"id":1
}
The result of serialization after disabling annotations:
{
"id":1,
"name":null
}
10. Заключение
Мы рассмотрели аннотации Jackson, которые при правильном использовании дают вам гибкость при сериализации/десериализации объектов.
Видео от автора оригинальной статьи:
Код примеров может быть найден по ссылке GitHub project – это maven-проект, и поэтому вам будет его легко импортировать и запустить.
Статья является творческим переводом оригинальной статьи.