1. Overview

In this article, we’ll do a deep dive into Jackson Annotations.

We’ll see how to use the existing annotations, how to create custom ones and finally – how to disable them.

Further reading:

More Jackson Annotations

This article covers some lesser-known JSON processing annotations provided by Jackson.

Read more →

Jackson – Bidirectional Relationships

How to use Jackson to break the infinite recursion problem on bidirectional relationships.

Read more →

Getting Started with Custom Deserialization in Jackson

Use Jackson to map custom JSON to any java entity graph with full control over the deserialization process.

Read more →

2. Jackson Serialization Annotations

First – let’s take a look at the serialization annotations.

2.1. @JsonAnyGetter

The @JsonAnyGetter annotation allows the flexibility of using a Map field as standard properties.

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:

1
2
3
4
5
6
7
8
9
public class ExtendableBean {
    public String name;
    private Map<String, String> properties;
 
    @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:

1
2
3
4
5
{
    "name":"My bean",
    "attr2":"val2",
    "attr1":"val1"
}

And here how the serialization of this entity looks like in practice:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
  throws JsonProcessingException {
  
    ExtendableBean bean = new ExtendableBean("My bean");
    bean.add("attr1", "val1");
    bean.add("attr2", "val2");
 
    String result = new ObjectMapper().writeValueAsString(bean);
  
    assertThat(result, containsString("attr1"));
    assertThat(result, containsString("val1"));
}

2.2. @JsonGetter

The @JsonGetter annotation is an alternative to the @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 MyBeanentity:

1
2
3
4
5
6
7
8
9
public class MyBean {
    public int id;
    private String name;
 
    @JsonGetter("name")
    public String getTheName() {
        return name;
    }
}

And here’s how this works in practice:

1
2
3
4
5
6
7
8
9
10
11
@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
  throws JsonProcessingException {
  
    MyBean bean = new MyBean(1, "My bean");
 
    String result = new ObjectMapper().writeValueAsString(bean);
  
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
}

2.3. @JsonPropertyOrder

The @JsonPropertyOrder annotation is used to specify the order of properties on serialization.

Let’s set a custom order for the properties of a MyBean entity:

1
2
3
4
5
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
    public int id;
    public String name;
}

And here is the output of serialization:

1
2
3
4
{
    "name":"My bean",
    "id":1
}

And a simple test:

1
2
3
4
5
6
7
8
9
10
@Test
public void whenSerializingUsingJsonPropertyOrder_thenCorrect()
  throws JsonProcessingException {
  
    MyBean bean = new MyBean(1, "My bean");
 
    String result = new ObjectMapper().writeValueAsString(bean);
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
}

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 a value of an entity:

1
2
3
4
5
6
public class RawBean {
    public String name;
 
    @JsonRawValue
    public String json;
}

The output of serializing the entity is:

1
2
3
4
5
6
{
    "name":"My bean",
    "json":{
        "attr":false
    }
}

And a simple test:

1
2
3
4
5
6
7
8
9
10
@Test
public void whenSerializingUsingJsonRawValue_thenCorrect()
  throws JsonProcessingException {
  
    RawBean bean = new RawBean("My bean", "{"attr":false}");
 
    String result = new ObjectMapper().writeValueAsString(bean);
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("{"attr":false}"));
}

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
public enum TypeEnumWithValue {
    TYPE1(1, "Type A"), TYPE2(2, "Type 2");
 
    private Integer id;
    private String name;
 
    // standard constructors
 
    @JsonValue
    public String getName() {
        return name;
    }
}

Our test:

1
2
3
4
5
6
7
8
9
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
  throws JsonParseException, IOException {
  
    String enumAsString = new ObjectMapper()
      .writeValueAsString(TypeEnumWithValue.TYPE1);
 
    assertThat(enumAsString, is(""Type A""));
}

2.6. @JsonRootName

The @JsonRootName annotation is used – if wrapping is enabled – to specify the name of the root wrapper to be used.

Wrapping means that instead of serializing a User to something like:

1
2
3
4
{
    "id": 1,
    "name": "John"
}

It’s going to be wrapped like this:

1
2
3
4
5
6
{
    "User": {
        "id": 1,
        "name": "John"
    }
}

So, let’s look at an example – we’re going to use the @JsonRootName annotation to indicate the name of this potential wrapper entity:

1
2
3
4
5
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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"));
}

Here is the output of serialization:

1
2
3
4
5
6
{
    "user":{
        "id":1,
        "name":"John"
    }
}

2.7. @JsonSerialize

@JsonSerialize is used to indicate a custom serializer will be used to marshall the entity.

Let’s look at a quick example – we’re going to use @JsonSerialize to serialize the eventDate property with a CustomDateSerializer:

1
2
3
4
5
6
public class Event {
    public String name;
 
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}

Here’s the simple custom Jackson serializer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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));
    }
}

Let’s use these in a test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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

Next – let’s explore the Jackson deserialization annotations.

3.1. @JsonCreator

The @JsonCreator annotation is used to tune the constructor/factory used in deserialization.

It’s very helpful when we need to deserialize some JSON that doesn’t exactly match the target entity we need to get.

Let’s look at an example; say we need to deserialize the following JSON:

1
2
3
4
{
    "id":1,
    "theName":"My bean"
}

However, there is no theName field in our target entity – there is only a name field. Now – we don’t 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:

1
2
3
4
5
6
7
8
9
10
11
12
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;
    }
}

Let’s see this in action:

1
2
3
4
5
6
7
8
9
10
11
@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 is used to indicate a property that will get its value from the injection and not from the JSON data.

In the following example – we use @JacksonInject to inject the property id:

1
2
3
4
5
6
public class BeanWithInject {
    @JacksonInject
    public int id;
     
    public String name;
}

And here’s how this works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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 allows you the flexibility of using a Map as standard properties. On de-serialization, the properties from JSON will simply be added to the map.

Let’s see how this works – we’ll use @JsonAnySetter to deserialize the entity ExtendableBean:

1
2
3
4
5
6
7
8
9
public class ExtendableBean {
    public String name;
    private Map<String, String> properties;
 
    @JsonAnySetter
    public void add(String key, String value) {
        properties.put(key, value);
    }
}

This is the JSON we need to deserialize:

1
2
3
4
5
{
    "name":"My bean",
    "attr2":"val2",
    "attr1":"val1"
}

And here’s how this all ties in together:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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 is an alternative to @JsonProperty – used to mark the method as a setter method.

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.

In the following example, we’ll specify the method setTheName() as the setter of the name property in our MyBeanentity:

1
2
3
4
5
6
7
8
9
public class MyBean {
    public int id;
    private String name;
 
    @JsonSetter("name")
    public void setTheName(String name) {
        this.name = name;
    }
}

Now, when we need to unmarshall some JSON data – this works perfectly well:

1
2
3
4
5
6
7
8
9
10
11
@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 is used to indicate the use of a custom deserializer.

Let’s see how that plays out – we’ll use @JsonDeserialize to deserialize the eventDate property with the CustomDateDeserializer:

1
2
3
4
5
6
public class Event {
    public String name;
 
    @JsonDeserialize(using = CustomDateDeserializer.class)
    public Date eventDate;
}

Here’s the custom deserializer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
        }
    }
}

And here’s the back-to-back test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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:

1
2
3
4
5
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
    public int id;
    public String name;
}

And here’s the test making sure the ignore happens:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
2
3
4
5
6
public class BeanWithIgnore {
    @JsonIgnore
    public int id;
 
    public String name;
}

And the test making sure that id was successfully ignored:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
2
3
4
5
6
7
8
9
10
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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:

1
2
3
4
5
@JsonInclude(Include.NON_NULL)
public class MyBean {
    public int id;
    public String name;
}

Here’s the full test:

1
2
3
4
5
6
7
8
9
10
11
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:

1
2
3
4
5
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
    private int id;
    private String name;
}

And the test:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
2
3
4
5
6
7
{
    "animal": {
        "type": "dog",
        "name": "lacy",
        "barkVolume": 0
    }
}

Now for de-serialization – let’s start with the following JSON input:

1
2
3
4
5
6
{
    "animal":{
        "name":"lacy",
        "type":"cat"
    }
}

And let’s see how that gets unmarshalled to a Zoo instance:

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
    String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
 
    Zoo zoo = new ObjectMapper()
      .readerFor(Zoo.class)
      .readValue(json);
 
    assertEquals("lacy", zoo.animal.name);
    assertEquals(Zoo.Cat.class, zoo.animal.getClass());
}

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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:

1
2
3
4
5
6
7
8
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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:

1
2
3
4
5
6
7
8
9
10
11
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:

1
2
3
4
5
6
7
8
9
10
11
@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:

1
2
3
4
5
{
    "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:

1
2
3
4
public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

And now here’s the Item entity, using the views:

1
2
3
4
5
6
7
8
9
10
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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 ItemWithRefentity:

1
2
3
4
5
6
7
public class ItemWithRef {
    public int id;
    public String itemName;
 
    @JsonManagedReference
    public UserWithRef owner;
}

Our UserWithRef entity:

1
2
3
4
5
6
7
public class UserWithRef {
    public int id;
    public String name;
 
    @JsonBackReference
    public List<ItemWithRef> userItems;
}

And the test:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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:

1
2
3
4
5
6
7
8
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class,
  property = "id")
public class ItemWithIdentity {
    public int id;
    public String itemName;
    public UserWithIdentity owner;
}

And the UserWithIdentity entity:

1
2
3
4
5
6
7
8
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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:

1
2
3
4
5
6
7
8
9
10
11
{
    "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:

1
2
3
4
5
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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 @JacksonAnnotationsInsideannotation – as in the following example:

1
2
3
4
5
@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:

1
2
3
4
5
6
@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:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
2
3
4
{
    "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:

1
2
3
4
5
public class Item {
    public int id;
    public String itemName;
    public User owner;
}
1
2
@JsonIgnoreType
public class MyMixInForIgnoreType {}

Let’s see this in action:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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:

1
2
3
4
5
6
@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:

1
2
3
4
5
6
7
8
9
10
11
12
@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:

1
{"id":1}

The result of serialization after disabling annotations:

1
2
3
4
{
    "id":1,
    "name":null
}

10. Conclusion

This tutorial has been a deep-dive into Jackson annotations, just scratching the surface of the kind of flexibility you can get using them correctly.

转载:https://www.baeldung.com/jackson-annotations

Jackson Annotation Examples的更多相关文章

  1. 练习:将值是null的数据删除掉(剔除):com.fasterxml.jackson.annotation.JsonInclude;包

    练习:将值是null的数据删除掉(剔除):com.fasterxml.jackson.annotation.JsonInclude;包 例如,有数据是null,不想展示 { "statusC ...

  2. fastxml Jackson annotation使用小记

    dependencies: compile("com.fasterxml.jackson.core:jackson-annotations") compile("com. ...

  3. NoClassDefFound Error: com/fasterxml/jackson/annotation/JsonAutoDetect

    少了 jackson-annotation https://blog.csdn.net/qq_36497454/article/details/80461676

  4. Jackson替换fastjson

    为什么要替换fastjson 工程里大量使用了fastjson作为序列化和反序列化框架,甚至ORM在处理部分字段也依赖fastjson进行序列化和反序列化.那么作为大量使用的基础框架,为什么还要进行替 ...

  5. Create JSON by Jackson API(转)

      原文地址: Create JSON by Jackson API Jackson API is a multi-purpose Java library for processing JSON. ...

  6. 【jackson 异常】com.fasterxml.jackson.databind.JsonMappingException异常处理

    项目中,父层是Gene.java[基因实体]  子层是Corlib.java[文集库实体],一种基因对用多个文集库文章 但是在查询文集库这个实体的时候报错:[com.fasterxml.jackson ...

  7. 使用 jackson 解析 json 演示样例

    首先须要下载3个包,下载地址在Github FasterXML,这三个核心模块各自是: Streaming ("jackson-core") defines low-level s ...

  8. Java下利用Jackson进行JSON解析和序列化

    Java下利用Jackson进行JSON解析和序列化   Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行 ...

  9. jackson annotations注解详解 (zhuan)

    http://blog.csdn.net/sdyy321/article/details/40298081 ************************************** 官方WIKI: ...

随机推荐

  1. day 14 - 1 生成器

    生成器 生成器 生成器的本质就是迭代器生成器的表现形式 生成器函数 生成器函数 —— 本质上就是我们自己写得函数 生成器表达式生成器函数: 含有 yield 关键字的函数就是生成器函数 特点: 调用函 ...

  2. Centos 06 文件类型和扩展名&索引节点inode和存储块block

    本节内容 1.文件类型 2.文件扩展名 3.索引节点inode和block块 首先需要申明一点, 1.在linux里面文件扩展名和文件类型是没有关系的 2.为了容易区分和兼容用户使用windows的习 ...

  3. SQL中笛卡尔积-cross join的用法

    在数学中,笛卡尔乘积是指两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 假设集合A={a ...

  4. 动态加载机Servlet容器加载器

    动态加载是Servlet 3.0中的新特性,它可以实现在 不重启Web应用的情况下加载新的Web对象(Servlet. Filter.Listener).Servlet容器加载器也是Servlet 3 ...

  5. C++中几个输入函数的用法和区别(cin、cin.get()、cin.getline()、getline()、gets()、getchar())

    1.cin>> 用法1:最基本,也是最常用的用法,输入一个数字: #include <iostream>using namespace std;main (){int a,b; ...

  6. Windows Internals 笔记——作业

    1.Windows提供了一个作业内核对象,它允许我们将进程组合在一起并创建一个“沙箱”来限制进程能够做什么.创建只包含一个进程的作业同样非常有用,因为这样可以对进程施加平时不能施加的限制. 2.如果进 ...

  7. 修正锚点跳转位置 避免头部fixed固定部分遮挡

    如下锚点标签: <div id="id1"> <span class="kkAnchor"></span> 正文正文正文正文 ...

  8. java开发学生信息管理系统的实现(简洁易懂),适合计算机专业学生参考,课程设计、毕业论文设计参考等

    编写一个简单的学生管理信息系统. 在oracle中设计一张学生表,以学号作为关键字. 其他学生信息有:姓名.手机号. 在进入系统时,显示如下菜单: ************************** ...

  9. .NET Core 添加Java 服务引用(WebService) 曲折历程(一)

    背景: 需要在HangFire定时任务中加入请求Java开发的WebService接口.定时获取数据同步数据.现有的代码是在VS2017 ,.Net Core 下创建的,添加WS发现系统不支持. 在C ...

  10. 关于postman各功能的说明及用法以及批量执行

    这玩意功能还不错,可以学学,在测试接口或者配合写代码测接口时是有帮助作用的.今天也去打听了一下,一下我就做了一下记录. 首先,主界面: 分开记录,写的详细一些. 左侧菜单栏: 主菜单(请求部分); 输 ...