Beispiele für Jackson-Anmerkungen

1. Übersicht

In diesem Tutorial werden wir uns eingehend mit Jackson Annotations befassen .

Wir werden sehen, wie Sie die vorhandenen Anmerkungen verwenden, benutzerdefinierte erstellen und schließlich deaktivieren.

2. Jackson Serialization Annotations

Zuerst werfen wir einen Blick auf die Serialisierungsanmerkungen.

2.1. @JsonAnyGetter

Die @JsonAnyGetter Annotation ermöglicht die Flexibilität der Verwendung eines Map - Feld als Standardeigenschaften.

Beispielsweise verfügt die ExtendableBean- Entität über die Eigenschaft name und eine Reihe erweiterbarer Attribute in Form von Schlüssel / Wert-Paaren:

public class ExtendableBean { public String name; private Map properties; @JsonAnyGetter public Map getProperties() { return properties; } }

Wenn wir eine Instanz dieser Entität serialisieren, erhalten wir alle Schlüsselwerte in der Map als einfache Standardeigenschaften:

{ "name":"My bean", "attr2":"val2", "attr1":"val1" }

So sieht die Serialisierung dieser Entität in der Praxis aus:

@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")); }

Wir können auch das optionale Argument verwenden aktiviert als falsch zu deaktivieren @JsonAnyGetter (). In diesem Fall wird die Map als JSON konvertiert und nach der Serialisierung unter der Eigenschaftsvariablen angezeigt.

2.2. @JsonGetter

Die Annotation @JsonGetter ist eine Alternative zur Annotation @JsonProperty , die eine Methode als Getter-Methode kennzeichnet.

Im folgenden Beispiel geben wir die Methode getTheName () als Getter-Methode der name- Eigenschaft einer MyBean- Entität an:

public class MyBean { public int id; private String name; @JsonGetter("name") public String getTheName() { return name; } }

So funktioniert das in der Praxis:

@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

Wir können die Annotation @JsonPropertyOrder verwenden , um die Reihenfolge der Eigenschaften bei der Serialisierung anzugeben .

Legen Sie eine benutzerdefinierte Reihenfolge für die Eigenschaften einer MyBean- Entität fest:

@JsonPropertyOrder({ "name", "id" }) public class MyBean { public int id; public String name; }

Hier ist die Ausgabe der Serialisierung:

{ "name":"My bean", "id":1 }

Dann können wir einen einfachen Test machen:

@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")); }

Wir können auch @JsonPropertyOrder (alphabetic = true) verwenden , um die Eigenschaften alphabetisch zu ordnen. In diesem Fall lautet die Ausgabe der Serialisierung:

{ "id":1, "name":"My bean" }

2.4. @JsonRawValue

Die Annotation @JsonRawValue kann Jackson anweisen, eine Eigenschaft genau so zu serialisieren, wie sie ist .

Im folgenden Beispiel verwenden wir @JsonRawValue , um benutzerdefinierten JSON als Wert einer Entität einzubetten:

public class RawBean { public String name; @JsonRawValue public String json; }

Die Ausgabe der Serialisierung der Entität lautet:

{ "name":"My bean", "json":{ "attr":false } }

Als nächstes folgt ein einfacher Test:

@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}")); }

Wir können auch den optionalen booleschen Argumentwert verwenden , der definiert, ob diese Annotation aktiv ist oder nicht.

2.5. @JsonValue

@JsonValue gibt eine einzelne Methode an, mit der die Bibliothek die gesamte Instanz serialisiert.

In einer Aufzählung versehen wir beispielsweise den getName mit @JsonValue, sodass eine solche Entität über ihren Namen serialisiert wird:

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; } }

Hier ist unser Test:

@Test public void whenSerializingUsingJsonValue_thenCorrect() throws JsonParseException, IOException { String enumAsString = new ObjectMapper() .writeValueAsString(TypeEnumWithValue.TYPE1); assertThat(enumAsString, is(""Type A"")); }

2.6. @JsonRootName

Die Annotation @JsonRootName wird verwendet, wenn der Umbruch aktiviert ist, um den Namen des zu verwendenden Root-Wrappers anzugeben.

Wrapping bedeutet, dass ein Benutzer nicht wie folgt serialisiert wird :

{ "id": 1, "name": "John" }

Es wird so verpackt:

{ "User": { "id": 1, "name": "John" } }

Schauen wir uns also ein Beispiel an. W ir gehen die verwenden @JsonRootName Annotation den Namen dieses Potential Wrapper Einheit , um anzuzeigen :

@JsonRootName(value = "user") public class UserWithRoot { public int id; public String name; }

Standardmäßig ist der Name des Wrappers der Name der Klasse - UserWithRoot . Durch die Verwendung der Anmerkung erhalten wir den sauberer aussehenden Benutzer:

@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")); }

Hier ist die Ausgabe der Serialisierung:

{ "user":{ "id":1, "name":"John" } }

Since Jackson 2.4, a new optional argument namespace is available to use with data formats such as XML. If we add it, it will become part of the fully qualified name:

@JsonRootName(value = "user", namespace="users") public class UserWithRootNamespace { public int id; public String name; // ... }

If we serialize it with XmlMapper, the output will be:

 1 John  

2.7. @JsonSerialize

@JsonSerialize indicates a custom serializer to use when marshalling the entity.

Let's look at a quick example. We're going to use @JsonSerialize to serialize the eventDate property with a CustomDateSerializer:

public class EventWithSerializer { public String name; @JsonSerialize(using = CustomDateSerializer.class) public Date eventDate; }

Here's the simple custom Jackson serializer:

public class CustomDateSerializer extends StdSerializer { private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateSerializer() { this(null); } public CustomDateSerializer(Class t) { super(t); } @Override public void serialize( Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { gen.writeString(formatter.format(value)); } }

Now let's use these in a test:

@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); EventWithSerializer event = new EventWithSerializer("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

We can use the @JsonCreator annotation to tune the constructor/factory used in deserialization.

It's very useful 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:

{ "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:

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:

@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 indicates that a property 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:

public class BeanWithInject { @JacksonInject public int id; public String name; }

Here's how it works:

@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 us the flexibility of using a Map as standard properties. On deserialization, the properties from JSON will simply be added to the map.

First, we'll use @JsonAnySetter to deserialize the entity ExtendableBean:

public class ExtendableBean { public String name; private Map properties; @JsonAnySetter public void add(String key, String value) { properties.put(key, value); } }

This is the JSON we need to deserialize:

{ "name":"My bean", "attr2":"val2", "attr1":"val1" }

Then here's how it all ties in together:

@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 that marks the method as a setter method.

This is incredibly 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 MyBean entity:

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:

@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 indicates the use of a custom deserializer.

First, we'll use @JsonDeserialize to deserialize the eventDate property with the CustomDateDeserializer:

public class EventWithSerializer { public String name; @JsonDeserialize(using = CustomDateDeserializer.class) public Date eventDate; }

Here's the custom deserializer:

public class CustomDateDeserializer extends StdDeserializer { 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); } } }

Next here's the back-to-back test:

@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"); EventWithSerializer event = new ObjectMapper() .readerFor(EventWithSerializer.class) .readValue(json); assertEquals( "20-12-2014 02:30:00", df.format(event.eventDate)); }

3.6. @JsonAlias

The @JsonAlias defines one or more alternative names for a property during deserialization.

Let's see how this annotation works with a quick example:

public class AliasBean { @JsonAlias({ "fName", "f_name" }) private String firstName; private String lastName; }

Here we have a POJO, and we want to deserialize JSON with values such as fName, f_name, and firstName into the firstName variable of the POJO.

Below is a test making sure this annotation works as expected:

@Test public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException { String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}"; AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json); assertEquals("John", aliasBean.getFirstName()); }

4. Jackson Property Inclusion Annotations

4.1. @JsonIgnoreProperties

@JsonIgnoreProperties is a class-level annotation that marks a property or a list of properties that Jackson will ignore.

Let's look at a quick example ignoring the property id from serialization:

@JsonIgnoreProperties({ "id" }) public class BeanWithIgnore { public int id; public String name; }

Now 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"))); }

To ignore any unknown properties in JSON input without exception, we can set ignoreUnknown=true of @JsonIgnoreProperties annotation.

4.2. @JsonIgnore

In contrast, 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; }

Then we'll test to make 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 marks all properties of an annotated type to be ignored.

We can 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; } }

We can also test to ensure 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

We can use @JsonInclude 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 can override the default semantics of which properties are visible and which are not.

First, 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; }

Then 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 – indicates details of what type information to include in serialization
  • @JsonSubTypes – indicates sub-types of the annotated type
  • @JsonTypeName – defines a logical type name to use for annotated class

Let's examine 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" } }

Then let's see how that gets unmarshalled to a Zoo instance:

@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's more general annotations.

6.1. @JsonProperty

We can add the @JsonProperty annotation to indicate the property name in JSON.

Let's 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; } }

Next is 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 specifies a format when serializing Date/Time values.

In the following example, we use @JsonFormat to control the format of the property eventDate:

public class EventWithFormat { public String name; @JsonFormat( shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") public Date eventDate; }

Then 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); EventWithFormat event = new EventWithFormat("party", date); String result = new ObjectMapper().writeValueAsString(event); assertThat(result, containsString(toParse)); }

6.3. @JsonUnwrapped

@JsonUnwrapped defines values that should be unwrapped/flattened when serialized/deserialized.

Let's see exactly how this 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; } }

Now let's 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"))); }

Finally, here's what 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 indicates the View in which the property will be included for serialization/deserialization.

For example, we'll use @JsonView to serialize an instance of Item entity.

First, let's start with the views:

public class Views { public static class Public {} public static class Internal extends Public {} }

Next 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 can 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 userItems; }

Then 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 indicates that Object Identity should be used when serializing/deserializing values, like when dealing with infinite recursion types of problems, for instance.

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; }

The UserWithIdentity entity:

@JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class UserWithIdentity { public int id; public String name; public List 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 use during serialization.

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:

@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 combines the existing annotations into a simple 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.

For example, let's use the MixIn annotations to ignore properties of type User:

public class Item { public int id; public String itemName; public User owner; }
@JsonIgnoreType public class MyMixInForIgnoreType {}

Then 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

Lassen Sie uns abschließend sehen, wie wir alle Jackson-Anmerkungen deaktivieren können . Wir können dies tun, indem wir das MapperFeature deaktivieren . USE_ANNOTATIONS wie im folgenden Beispiel:

@JsonInclude(Include.NON_NULL) @JsonPropertyOrder({ "name", "id" }) public class MyBean { public int id; public String name; }

Nach dem Deaktivieren von Anmerkungen sollten diese nun keine Auswirkungen mehr haben und die Standardeinstellungen der Bibliothek sollten gelten:

@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")); }

Das Ergebnis der Serialisierung vor dem Deaktivieren von Anmerkungen:

{"id":1}

Das Ergebnis der Serialisierung nach dem Deaktivieren von Anmerkungen:

{ "id":1, "name":null }

10. Schlussfolgerung

In diesem Artikel haben wir Jackson-Anmerkungen untersucht und dabei nur die Oberfläche der Flexibilität zerkratzt, die wir durch korrekte Verwendung erhalten können.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie auf GitHub.