1. 概述

在本文中,我们将深入研究Jackson注解。

我们将看到如何使用现有的注释,如何创建自定义的注释,最后—如何禁用它们。

2. Jackson序列化注解

首先,我们将查看序列化注释。

2.1. @JsonAnyGetter

@JsonAnyGetter注释允许灵活地使用映射字段作为标准属性。

下面是一个快速的例子——ExtendableBean实体拥有name属性和一组可扩展属性,它们以键/值对的形式存在:

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

当我们序列化这个实体的一个实例时,我们会得到Map中所有的键值作为标准的普通属性:

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

这里是如何序列化这个实体看起来像在实践:

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

我们还可以使用可选参数enabled为false来禁用@JsonAnyGetter()。在本例中,映射将被转换为JSON,并在序列化之后出现在properties变量下。

2.2. @JsonGetter

@JsonGetter注释是@JsonProperty注释的替代品,它将方法标记为getter方法。

在下面的例子中-我们指定getTheName()方法作为MyBean实体的name属性的getter方法:

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

这是如何在实践中运作的:

@Testpublic 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

我们可以使用@JsonPropertyOrder注释来指定序列化时属性的顺序。

让我们为MyBean实体的属性设置一个自定义顺序:

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

这是序列化的输出:

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

还有一个简单的测试:

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

我们还可以使用@JsonPropertyOrder(alphabetic=true)按字母顺序排列属性。在这种情况下,序列化的输出将是:

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

2.4. @JsonRawValue

@JsonRawValue注释可以指示Jackson按原样序列化属性。

在下面的例子中,我们使用@JsonRawValue嵌入一些定制的JSON作为一个实体的值:

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

序列化实体的输出为:

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

还有一个简单的测试:

@Testpublic 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表示库将使用一个方法来序列化整个实例。

例如,在枚举中,我们用@JsonValue注释getName,这样任何这样的实体都可以通过其名称序列化:

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

我们的测试:

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

2.6. @JsonRootName

如果启用了包装,则使用@JsonRootName注释来指定要使用的根包装器的名称。

包装意味着不将用户序列化为以下内容:

它会像这样包装:

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

那么,让我们来看一个例子——我们将使用@JsonRootName注释来表示这个潜在的包装实体的名称:

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

默认情况下,包装器的名称将是类的名称- UserWithRoot。通过使用注释,我们得到了看起来更干净的用户:

@Testpublic 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"    }}

自Jackson 2.4以来,一个新的可选参数名称空间可用于XML等数据格式。如果我们添加它,它将成为完全限定名的一部分:

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

如果我们用XmlMapper序列化它,输出将是:

1John

2.7. @JsonSerialize

让我们看一个简单的例子。我们将使用@JsonSerialize用CustomDateSerializer来序列化eventDate属性:

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

下面是简单的自定义Jackson序列化器:

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

让我们在测试中使用这些:

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

Jackson反序列化注解

接下来——让我们研究Jackson反序列化注解。

3.1. @JsonCreator

我们可以使用@JsonCreator注释来调优反序列化中使用的构造器/工厂。

当我们需要反序列化一些与我们需要获取的目标实体不完全匹配的JSON时,它非常有用。

我们来看一个例子;说我们需要反序列化以下JSON:

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

但是,在我们的目标实体中没有theName字段—只有name字段。现在,我们不想改变实体本身—我们只需要对数据编出过程进行更多的控制—通过使用@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;    }}

让我们来看看这是怎么回事:

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

它是这样工作的:

@Testpublic 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允许我们灵活地使用映射作为标准属性。在反序列化时,JSON的属性将被添加到映射中。

让我们看看这是如何工作的-我们将使用@JsonAnySetter来反序列化实体ExtendableBean:

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

这是我们需要反序列化的JSON:

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

而这一切是如何联系在一起的:

@Testpublic 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的替代方法—它将方法标记为setter方法。

当我们需要读取一些JSON数据,但目标实体类与该数据不完全匹配时,这非常有用,因此我们需要调优流程以使其适合该数据。

在下面的例子中,我们将指定方法setTheName()作为MyBean实体中name属性的setter:

public class MyBean {    public int id;    private String name;     @JsonSetter("name")    public void setTheName(String name) {        this.name = name;    }}

现在,当我们需要unmarshall一些JSON数据-这是完美的工作:

@Testpublic 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表示使用自定义反序列化器。

让我们看看这是如何实现的-我们将使用@JsonDeserialize来反序列化eventDate属性与CustomDateDeserializer:

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

这是自定义反序列化器:

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

这是背靠背的测试:

@Testpublic 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

@JsonAlias在反序列化期间为属性定义一个或多个替代名称。

让我们通过一个简单的例子来看看这个注释是如何工作的:

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

在这里,我们有一个POJO,我们想用fName、f_name和firstName等值反序列化JSON到POJO的firstName变量中。

这里有一个测试,确保这个注释像expecte一样工作:

@Testpublic 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属性包含注释

4.1. @JsonIgnoreProperties

@JsonIgnoreProperties是一个类级注释,它标记Jackson将忽略的一个属性或一列属性。

让我们来看一个忽略属性id的例子:

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

下面是确保忽略发生的测试:

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

为了毫无例外地忽略JSON输入中的任何未知属性,我们可以对@JsonIgnoreProperties注释设置ignoreUnknown=true。

4.2. @JsonIgnore

@JsonIgnore注释用于在字段级别标记要忽略的属性。

让我们使用@JsonIgnore来忽略序列化中的属性id:

public class BeanWithIgnore {    @JsonIgnore    public int id;     public String name;}

确保id被成功忽略的测试:

@Testpublic 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将注释类型的所有属性标记为忽略。

让我们使用注释来标记所有类型名称的属性被忽略:

public class User {    public int id;    public Name name;     @JsonIgnoreType    public static class Name {        public String firstName;        public String lastName;    }}

这里有一个简单的测试,确保忽略工作正确:

@Testpublic 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来排除具有空/空/默认值的属性。

让我们看一个例子-排除null从序列化:

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

下面是完整的测试:

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可以覆盖哪些属性可见,哪些不可见的默认语义。

让我们通过一个简单的例子来看看这个注释是如何非常有用的——让我们启用序列化私有属性:

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

测试:

@Testpublic 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多态类型处理注释

接下来,让我们看看Jackson多态类型处理注释:

  • @JsonTypeInfo——指示要在序列化中包含什么类型信息的详细信息
  • @JsonSubTypes——指示注释类型的子类型
  • @JsonTypeName—定义了一个用于注释类的逻辑类型名

让我们看一个更复杂的例子,使用所有这三个——@JsonTypeInfo, @JsonSubTypes,和@JsonTypeName——来序列化/反序列化实体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;    }}

当我们进行序列化时:

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

下面是将动物园实例与狗序列化将得到的结果:

{    "animal": {        "type": "dog",        "name": "lacy",        "barkVolume": 0    }}

现在反序列化-让我们从以下JSON输入开始:

{    "animal":{        "name":"lacy",        "type":"cat"    }}

让我们看看它是如何被分解到一个动物园实例的:

@Testpublic 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通用注解

接下来——让我们讨论Jackson的一些更通用的注释。

6.1. @JsonProperty

我们可以添加@JsonProperty注释来表示JSON中的属性名。

当我们处理非标准的getter和setter时,让我们使用@JsonProperty来序列化/反序列化属性名:

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

我们的测试:

@Testpublic 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

@JsonFormat注释在序列化日期/时间值时指定一种格式。

在下面的例子中,我们使用@JsonFormat来控制属性eventDate的格式:

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

下面是测试:

@Testpublic 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定义了在序列化/反序列化时应该被解包装/扁平化的值。

我们来看看它是如何工作的;我们将使用注释来展开属性名:

public class UnwrappedUser {    public int id;     @JsonUnwrapped    public Name name;     public static class Name {        public String firstName;        public String lastName;    }}

现在让我们序列化这个类的一个实例:

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

下面是输出的样子-静态嵌套类的字段与其他字段一起展开:

{    "id":1,    "firstName":"John",    "lastName":"Doe"}

6.4. @JsonView

@JsonView表示将包含该属性进行序列化/反序列化的视图。

我们将使用@JsonView来序列化项目实体的实例。

让我们从视图开始:

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

现在这是Item实体,使用视图:

public class Item {    @JsonView(Views.Public.class)    public int id;     @JsonView(Views.Public.class)    public String itemName;     @JsonView(Views.Internal.class)    public String ownerName;}

最后-完整测试:

@Testpublic 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

@JsonManagedReference和@JsonBackReference注释可以处理父/子关系并在循环中工作。

在下面的例子中-我们使用@JsonManagedReference和@JsonBackReference来序列化我们的ItemWithRef实体:

public class ItemWithRef {    public int id;    public String itemName;     @JsonManagedReference    public UserWithRef owner;}

我们的UserWithRef实体:

public class UserWithRef {    public int id;    public String name;     @JsonBackReference    public List userItems;}

测试:

@Testpublic 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表示在序列化/反序列化值时应该使用对象标识—例如,用于处理无限递归类型的问题。

在下面的例子中-我们有一个ItemWithIdentity实体,它与UserWithIdentity实体具有双向关系:

@JsonIdentityInfo(  generator = ObjectIdGenerators.PropertyGenerator.class,  property = "id")public class ItemWithIdentity {    public int id;    public String itemName;    public UserWithIdentity owner;}

和UserWithIdentity实体:

@JsonIdentityInfo(  generator = ObjectIdGenerators.PropertyGenerator.class,  property = "id")public class UserWithIdentity {    public int id;    public String name;    public List userItems;}

现在,让我们看看无限递归问题是如何处理的:

@Testpublic void whenSerializingUsingJsonIdentityInfo_thenCorrect()  throws JsonProcessingException {    UserWithIdentity user = new UserWithIdentity(1, "John");    ItemWithIdentity item = new ItemWithIdentity(2, "book", user);    user.addItem(item);     String result = new ObjectMapper().writeValueAsString(item);     assertThat(result, containsString("book"));    assertThat(result, containsString("John"));    assertThat(result, containsString("userItems"));}

下面是序列化的项目和用户的完整输出:

{    "id": 2,    "itemName": "book",    "owner": {        "id": 1,        "name": "John",        "userItems": [            2        ]    }}

6.7. @JsonFilter

@JsonFilter注释指定要在序列化期间使用的过滤器。

让我们看一个例子;首先,我们定义实体,并指向过滤器:

@JsonFilter("myFilter")public class BeanWithFilter {    public int id;    public String name;}

现在,在完整的测试中,我们定义了过滤器——它排除了序列化中除了name之外的所有其他属性:

@Testpublic 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. Jackson自定义注释

接下来,让我们看看如何创建自定义Jackson注释。我们可以使用@JacksonAnnotationsInside注释:

@Retention(RetentionPolicy.RUNTIME)    @JacksonAnnotationsInside    @JsonInclude(Include.NON_NULL)    @JsonPropertyOrder({ "name", "id", "dateCreated" })    public @interface CustomAnnotation {}

现在,如果我们对一个实体使用新的注释:

@CustomAnnotationpublic class BeanWithCustomAnnotation {    public int id;    public String name;    public Date dateCreated;}

我们可以看到它是如何将现有的注解组合成一个更简单的、自定义的注解,我们可以使用它作为速记:

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

序列化过程的输出:

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

8. Jackson MixIn 注解

接下来——让我们看看如何使用Jackson MixIn注释。

让我们使用MixIn注释——例如——忽略类型User的属性:

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

让我们来看看这是怎么回事:

@Testpublic 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. 禁用Jackson注解

最后,让我们看看如何禁用所有Jackson注释。我们可以通过禁用MapperFeature来做到这一点。如下例所示:

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

现在,禁用注释后,这些应该没有效果,库的默认值应该适用:

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

禁用注释之前序列化的结果:

{"id":1}

禁用注释后序列化的结果:

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

10. 结论

本教程对Jackson注释进行了深入的研究,只触及了正确使用它们所能获得的灵活性的表面。

jsonproperty注解_Jackson注解详解相关推荐

  1. 源代码下载 第六章 注解式控制器详解

    2019独角兽企业重金招聘Python工程师标准>>> 源代码请到附件中下载. 其他下载: 跟着开涛学SpringMVC 第一章源代码下载 第二章 Spring MVC入门 源代码下 ...

  2. SpringBoot注解最全详解(整合超详细版本)

    今日推荐强制双休!腾讯调整加班机制,21 点前必须离开工位 使用雪花id或uuid作为Mysql主键,被老板怼了一顿! 盘点 12 个 GitHub 上的高仿项目 CTO 说了,用错 @Autowir ...

  3. java的注解方式_详解Java注解的实现与使用方法

    详解Java注解的实现与使用方法 Java注解是java5版本发布的,其作用就是节省配置文件,增强代码可读性.在如今各种框架及开发中非常常见,特此说明一下. 如何创建一个注解 每一个自定义的注解都由四 ...

  4. @Column注解及属性详解

    @Column注解 用来标识实体类中属性与数据表中字段的对应关系 (1)源码: /** Copyright (c) 2008, 2009, 2011 Oracle, Inc. All rights r ...

  5. Android -- Annotation(注解)原理详解及常见框架应用

    1,我们在上一篇讲到了EventBus源码及3.0版本的简单使用,知道了我们3.0版本是使用注解方式标记事件响应方法的,这里我们就有一个疑问了,为什么在一个方法加上类似于"@Subscrib ...

  6. JavaWeb-Spring中注解大全与详解

    常用的spring注解有如下几种: @Controller @Service @Autowired @RequestMapping @RequestParam @ModelAttribute @Cac ...

  7. Java注解处理器使用详解

    文章转自:http://www.race604.com/annotation-processing/ 在这篇文章中,我将阐述怎样写一个注解处理器(Annotation Processor).在这篇教程 ...

  8. Spring注解之@GetMapping详解

    params 参数详解 例如:@GetMapping(value = "/service", params = "serviceName=CREATE_PROJECT&q ...

  9. Java注解解读-ElementType详解

    文章目录 注解须知前言 @Target @Retention @Inherited @Documented @Repeatable 注解须知前言 Java注解使用是相当频繁,特别是在在框架源码使用,用 ...

  10. Spring注解之Service详解

    目录 @[TOC](目录) Service注解 Service用法及示例 传统方式是怎么做的呢? @Service注解是怎么体现业务逻辑复用的? 总结 Service注解 @Service 注解是 S ...

最新文章

  1. MFC消息处理学习总结
  2. mysql聚集索引和二级索引_mysql8 参考手册--聚集索引和二级索引
  3. python开启新代码块_20课零基础快速学python完成简单邮件完整邮件代码块
  4. android 微信设置圆角边框代码,Android编程实现圆角边框的方法
  5. Cocos2dx ParticleEditor粒子编辑器
  6. m126a linux驱动下载,【惠普m126a驱动】惠普m126a驱动下载 v15.0 官方版-开心电玩
  7. 国外大神在GitHub上发布的打包成APP的Win95
  8. 网易秋招编程题——优雅的点
  9. 融云对接php,谈谈微信小程序中首次对接融云WebIM SDK经验
  10. 一个故事带你看透HTTPS(上)
  11. 光学载波网络(SONET OC)的网络带宽
  12. unity找到指定名称的一个物体的子物体,多个子物体有相同的名称
  13. 【CCM-SLAM论文阅读笔记】
  14. w10计算机怎么恢复出厂设置路由器,技术编辑为你解决win10系统打不开192.168.1.1设置界面的还原步骤...
  15. 微信小程序键盘弹起后页面上推问题
  16. 试题 算法训练 黑色星期五
  17. ###好好好####深度学习---多标签分类问题
  18. *1 计算机基础和操作系统基础及几大协议
  19. 关闭iframe中弹窗,视频也关闭播放
  20. rabbit mq Consumer Acknowledgements and Publisher Confirms 翻译

热门文章

  1. 求助matlab分解质因数,Matlab
  2. android log4,GitHub - oronno/log4android: Log4Android - Simple Logging Wrapper Library for Android
  3. python入门之控制结构-循环结构_(一)Python入门-4控制语句:05while循环结构-死循环处理...
  4. unix 存储空间不足 无法处理此命令_大数据分析命令行使用教程
  5. 一行代码快速搞定Flowable断点下载(下)
  6. 无线基站侧的信令风暴根因——频繁的释放和连接RRC产生大量信令、设备移动导致小区重选信令增加、寻呼信令多...
  7. VoltDB介绍——本质:数据保存在内存,充分利用CPU,单线程去锁,底层数据结构未知...
  8. 在CentOS上安装Python
  9. notepad++取消语法检测
  10. Grinder搭建小记与Nduja(这次不待续了)