К оглавлению 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), которой можно пометить определённый метод как геттер.
В следующем примере помечаем разные методы класса 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), для указания названия корневого элемента.
Вложенность означает, что при сериализации класса 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-проект, и поэтому вам будет его легко импортировать и запустить.
Статья является творческим переводом оригинальной статьи.