杰克逊顶部

从Spring 5和Spring Boot 2开始学习春天课程:

>>查看课程

1.概述

在本教程中,我们将深入潜入杰克逊注释

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

进一步阅读:

更多杰克逊诠释

本文将介绍Jackson提供的一些不太为人所知的JSON处理注释。

杰克逊 - 双向关系

如何使用杰克逊在双向关系中打破无限递归问题。

jackson中的自定义反序列化入门

使用Jackson将自定义JSON映射到任何Java实体图形,并完全控制反序列化进程。

2.杰克逊序列化注释

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

2.1.@JsonAnyGetter

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

例如,延伸的实体的名称属性和一组键/值对形式的可扩展属性:

public class ExtendableBean {public String name;private Map属性;@JsonAnyGetter public Map getProperties(){返回属性;}}

当我们序列化此实体的实例时,我们会获得所有密钥值地图作为标准,普通属性:

{“名称”:“我的豆”,“attr2”:“val2”、“attr1”:“val1”}

这是本实体的序列化在实践中的看法:

@test public void whenserializationusingjsonanygetter_thencorrect()抛出jsonprocessingexception {extendablebean bean = new extendablebean(“我的bean”);bean.add(“attr1”,“val1”);Bean.add(“attr2”,“val2”);String result = new objectapper (). writevaleasstring (bean);assertthat(结果,包含(“attr1”));assertthat(结果,包含(“Val1”));}

我们也可以使用可选参数启用作为禁用@jsonanygetter()。在这种情况下,地图将被转换为json,并将出现在属性序列化后变量。

2.2。@JsonGetter

@JsonGetter注释是一种替代方案@jsonproperty.注释,将方法标记为Getter方法。

在下面的例子中,我们指定了这个方法getTheName ()作为Getter方法名称A的财产mybean.实体:

public class MyBean {public int id;私人字符串名称;@JsonGetter("name") public String getname(){返回名称;}}

下面是它在实践中的工作方式:

@test public void whenserializationusingjsongetter_thencorrect()抛出jsonprocessingexception {mybean bean = new mybean(1,“我的bean”);String result = new objectapper (). writevaleasstring (bean);为了(因此,containsString(“我的bean”));为了(因此,containsString (" 1 "));}

2.3。@jsonpropertyorder.

我们可以使用@jsonpropertyorder.注释指定属性序列化的顺序

让我们为a的属性设置自定义顺序mybean.实体:

@jsonpropertyorder({“name”,“ID”})公共类MyBean {Public Int ID;公共字符串名称;}

下面是序列化的输出:

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

然后我们可以做一个简单的测试

@test public void whenserializedusingjsonpropertyorder_thencorrect()抛出jsonprocessingexception {mybean bean = new mybean(1,“我的bean”);String result = new objectapper (). writevaleasstring (bean);为了(因此,containsString(“我的bean”));为了(因此,containsString (" 1 "));}

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

{“ID”:1,“名称”:“我的豆”}

2.4。@JsonRawValue

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

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

公共类Rawbean {公共字符串名称;@jsonrawvalue公共字符串json;}

序列化实体的输出是:

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

接下来这是一个简单的测试:

@Test public void whenSerializingUsingJsonRawValue_thenCorrect() throws JsonProcessingException {RawBean bean = new RawBean("我的bean", "{\"attr\":false}");String result = new objectapper (). writevaleasstring (bean);为了(因此,containsString(“我的bean”));为了(因此,containsString(“{\“attr \”:假}"));}

我们还可以使用可选的布尔参数价值定义此注释是否处于活动状态。

2.5。@jsonvalue.

@jsonvalue.指示库将使用的单个方法来序列化整个实例。

例如,在一个枚举中,我们注释了getName.@jsonvalue.所以任何这样的实体都是通过它的名字序列化的:

公共枚举typeenumwithvalue {type1(1,“类型a”),type2(2,“2”);私有整数ID;私人字符串名称;//标准构造函数@jsonvalue public string getName(){返回名称;}}

现在这是我们的测试:

@Test公共void whenserializationusingjsonvalue_thencorrect()抛出jsonparseexception,ioException {string enumasstring = new objectmapper().writevalueastring(typeenumwithvalue.type1);assertthat(enumasstring,是(“”类型a“));}

2.6。@jsonrootname.

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

包装意味着,而不是序列化a用户到类似的东西:

{“ID”:1,“名称”:“John”}

它将被包裹如下:

{“用户”:{“ID”:1,“名称”:“John”}}

我们来看一个例子。W.e're将使用@jsonrootname.注释表示此潜在包装实体的名称

@JsonRootName(value = "user") public class UserWithRoot {public int id;公共字符串名称;}

默认情况下,包装器的名称将是类的名称 -UserWithroot..通过使用注释,我们得到了更清晰的外观用户:

@test public void whenserializationusingjsonrootname_thencorrect()抛出jsonprocessingexception {userwithroot用户=新用户(1,“John”);objectapper = new objectapper ();Mapper.Enable(SerializationFeature.Wrap_root_Value);String结果= Mapper.WriteValueAstring(用户);asserthat(结果,包含(“John”));assertthat(结果,包含(“用户”));}

下面是序列化的输出:

{“用户”:{“ID”:1,“名称”:“John”}}

自杰克逊2.4以来,一个新的可选论点命名空间可用于与XML等数据格式一起使用。如果我们添加它,它将成为完全限定名称的一部分:

@JsonRootName(value ="user ", namespace="users") public class UserWithRootNamespace {public int id;公共字符串名称;/ /……}

如果我们用XMLMapper,输出将是:

<用户XMLNS =“用户”>  1   John  <项目XMLNS =“”/> 

2.7。@jsonserialize.

@jsonserialize.指示何时使用的自定义序列化器编组的实体。

让我们看一个简单的例子。我们要用@jsonserialize.序列化的活动日期财产与CustomDateSerializer

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

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

@test public void whenserializedusingjsonserialize_thencorrect()抛出jsonprocessingException,parseexception {simpleDateformat Df = New SimpleDateFormat(“DD-MM-YYYY HH:MM:SS”);字符串toparse =“20-12-2014 02:30:00”;日期日期= df.parse(toparse);EventWithSerializer事件=新的EventWithSerializer(“派对”,日期);String结果= new objectMapper()。writevalueastring(事件);asserthat(结果,包含(Toparse));}

杰克逊反序列化注释

接下来让我们探索杰克逊的解串化注释。

3.1。@jsoncreator.

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

当我们需要反序列化某些与我们需要得到的目标实体完全匹配的JSON时非常有用。

让我们来看看一个例子。假设我们需要将以下JSON进行反序列化:

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

但是,没有领域在我们的目标实体中,只有一个名称场地。现在我们不想改变实体本身,我们只需通过注释构造函数来更长的控制对解码过程@jsoncreator,和使用@jsonproperty.注释:

public class BeanWithCreator {public int id;公共字符串名称;@JsonProperty public BeanWithCreator(@JsonProperty("id") int id, @JsonProperty(" name ") String name){这个。id = id;this.name =名称;}}

让我们在行动中看到这一点:

@Test public void whenDeserializingUsingJsonCreator_thenCorrect() throws IOException {String json = "{\"id\":1,\" name \":\"My bean\"}";BeanWithCreator bean = new objectapper () .readerFor(BeanWithCreator.class) .readValue(json);assertequal(“我的豆”,bean.name);}

3.2。@jacksoninject.

@jacksoninject.表示属性将从注射中获得其值而不是JSON数据。

在下面的例子中,我们使用@jacksoninject.注入房产id

公共类BeanWithInject {@jacksonInject public int id;公共字符串名称;}

这是它的工作原理:

@Test public void whenDeserializingUsingJsonInject_thenCorrect() throws IOException {String json = "{\"name\":\"My bean\"}";注入= new InjectableValues. std () .addValue(int.class, 1);BeanWithInject bean = new objectapper ().reader(inject) .forType(BeanWithInject.class) .readValue(json);assertequal(“我的豆”,bean.name);bean.id assertequal(1日);}

3.3.@JSonanysetter.

@JSonanysetter.允许我们使用a的灵活性地图作为标准属性。在反序列化上,JSON的属性将简单地添加到地图中。

首先,我们将使用@JSonanysetter.将实体反序列化延伸的

public class ExtendableBean {public String name;private Map属性;@jsonanysetter public void添加(String键,字符串值){properties.put(key,value);}}

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

{“名称”:“我的豆”,“attr2”:“val2”、“attr1”:“val1”}

然后这里是如何共同联系的:

@test public void whendeserializingusingjsonanysetter_thencorrect()抛出ioException {String Json =“{\”name \“:\”我的bean \“,\”attr2 \“:\”val2 \“,\”attr1 \“:\”val1 \“}”;扩展的bean = new objectmapper().readerfor(扩展区域).readvalue(JSON);assertequal(“我的豆”,bean.name);assertequals(“val2”,bean.getproperties()。获得(“attr2”));}

3.4.@JsonSetter

@JsonSetter是替代@jsonproperty.将该方法标记为Setter方法。

当我们需要阅读一些JSON数据时,这非常有用,但是目标实体类与该数据不完全匹配,因此我们需要调整过程,使之适合。

在以下示例中,我们将指定方法setTheName ()的setter名称在我们的财产mybean.实体:

public class MyBean {public int id;私人字符串名称;@JsonSetter("name") public void setname (String name) {this.name = name;}}

现在,当我们需要解开一些JSON数据时,这会完美良好:

@test public void whendeserializingusingjsonsetter_thencorrect()抛出ioException {string json =“{\”id \“:1,\”name \“:\”我的bean \“}”;mybean bean = new objectmapper().readerfor(mybean.class).readvalue(JSON);assertequals(“我的bean”,bean.getthename());}

3.5。@jsondeserialize.

@jsondeserialize.指示使用自定义反序列化器。

首先,我们将使用@jsondeserialize.反驳这一点活动日期财产的CustomDateDeserializer

public class EventWithSerializer {public String name;@jsondeserialize(使用= customdatedeserializer.class)公共日期eventdate;}

下面是自定义反序列化器:

公共类CustomDateDeserializer扩展了StdDeserializer <日期> {私有静态SimpledateFormat格式化程序= New SimpleDateFormat(“DD-MM-YYYY HH:MM:SS”);公共customdatedeserializer(){这个(null);public customdatedeserializer(类<?> vc){super(vc);@Override公共日期deserialize(jsonparser jsonparser,deserializationcontext上下文)抛出ioException {string date = jsonparser.gettext();尝试{return formatter.parse(日期);捕获(ParseException e){抛出新的runtimeexception(e);}}}

接下来这是背靠背测试:

@test public void whendeserializingusingjsondeserialize_thencorrect()抛出ioException {String Json =“{”name“:”派对“,”eventdate“:”20-12-2014 02:30:00“}”;SimpleDateFormat DF = New SimpleDateFormat(“DD-MM-YYYY HH:MM:SS”);EventWithSerializer事件= New ObjectMapper().readerfor(EventWithSerializer.class).readValue(JSON);assertequals(“20-12-2014 02:30:00”,df.format(Event.Eventdate));}

3.6。@JsonAlias

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

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

公共类别aliasbean {@jsonalias({“fname”,“f_name”})私有字符串名称;私有字符串LastName;}

在这里,我们有一个pojo,我们希望使用诸如的价值观(如)反驳jsonf_name., 和变量POJO。

下面是一个测试,以确保该注释按预期工作:

@Test public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";new objectapper ().readerFor(AliasBean.class).readValue(json);assertequal(“约翰”,aliasBean.getFirstName ());}

4.杰克逊财产纳入注释

4.1。@jsonignoreproperties.

@jsonignoreproperties.是一个类级注释,标志着杰克逊将忽略的属性或属性列表。

让我们来看看一个快速的例子,忽略了这个属性id从序列化:

@jsonignoreproperties({id“})公共类beanwithignore {public int id;公共字符串名称;}

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

@test public void whenserializedusingjsonignoreproperties_thencorrect()抛出jsonprocessingexception {beanwithignore bean = new beanwithignore(1,“我的bean”);字符串结果= new objectmapper().writevalueastring(bean);为了(因此,containsString(“我的bean”));assertthat(结果,不是(包含(“ID”))));}

要忽略JSON输入中的任何未知属性而无需异常,我们可以设置Ignoreunknown =真实@jsonignoreproperties.注解。

4.2.@jsonignore.

相比之下,@jsonignore.注释用于标记在现场级别忽略的属性。

让我们使用@jsonignore.忽略房产id从序列化:

public class BeanWithIgnore {@JsonIgnore public int id;公共字符串名称;}

然后我们将测试以确保id被成功被忽略:

@test public void whenserializedusingjsonignore_thencorrect()抛出jsonprocessingexception {beanwithignore bean = new beanwithignore(1,“我的bean”);字符串结果= new objectmapper().writevalueastring(bean);为了(因此,containsString(“我的bean”));assertthat(结果,不是(包含(“ID”))));}

4.3.@jsonignoretype.

@jsonignoretype.将注释类型的所有属性标记为忽略。

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

public class User {public int id;公共名称名称;@JsonIgnoreType public static class Name {public String firstName;公共字符串姓;}}

我们还可以测试以确保忽略正常工作:

@test public void whenserializedusingjsonignoretype_thencorrect()抛出jsonprocessingexception,parseexception {user.name name = new user.name(“John”,“Doe”);用户用户=新用户(1,名称);String结果= new objectmapper().writevalueastring(用户);为了(因此,containsString (" 1 "));asserthat(结果,不是(包含(“名称”))));assertthat(结果,不是(包含(“约翰”))));}

4.4。@jsoninclude

我们可以用@jsoninclude排除具有空/空/默认值的属性。

让我们看一个从序列化中排除空值的例子:

@jsoninclude(include.non_null)公共类mybean {public int id;公共字符串名称;}

这是完整的测试:

public void whenseralizationusingjsoninclude_thencorrect()抛出jsonprocessingexception {mybean bean = new mybean(1,null);字符串结果= new objectmapper().writevalueastring(bean);为了(因此,containsString (" 1 "));asserthat(结果,不是(包含(“名称”))));}

4.5。@jsonautodetect.

@jsonautodetect.可以覆盖默认的语义哪个属性可见,哪些属性不是

首先,让我们来看看如何用简单的例子非常有用;让我们启用序列化私有属性:

@jsonautodetect(timentvisibility =可见性.Any)公共类私人{私人int id;私人字符串名称;}

然后测试:

@test public void whenserializationusingjsonautodetect_thencorrect()抛出jsonprocessingexception {privatebean bean = new privatebean(1,“我的bean”);字符串结果= new objectmapper().writevalueastring(bean);为了(因此,containsString (" 1 "));为了(因此,containsString(“我的bean”));}

5.Jackson多态类型处理注释

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

  • @JsonTypeInfo-表示序列化中要包含的类型信息的详细信息
  • @jsonsubtypes.- 表示注释类型的子类型
  • @jsontypename.- 定义要用于注释类的逻辑类型名称

让我们来检查一个更复杂的例子,并使用这三个 -@JsonTypeInfo@jsonsubtypes,@jsontypename -序列化/反统化实体动物园

公共类动物园{公共动物动物;@jsontypeinfo(使用= jsontypeinfo.id.name,include = as.property,property =“type”)@jsonsubtypes({@ jsonsubtypes.type(value = dog.class,name =“dog”),@ jsonsubtypes.type(value = cat.class,name =“cat”)})公共静态类动物{public string名称;@jsontypename(“狗”)公共静态犬延伸动物{公共双巴克窗;@jsontypename(“cat”)公共静态类猫延伸了动物{布尔喜欢浏览;公共INT;}}

当我们进行序列化时:

@Test public void whenSerializingPolymorphic_thenCorrect() throws JsonProcessingException{动物园。new Zoo.Dog = new Zoo.Dog("蕾丝");Zoo = new Zoo(狗);String result = new objectapper () . writevaleasstring (zoo);为了(因此,containsString(“类型”));为了(因此,containsString(“狗”));}

这就是序列化动物园实例与将导致:

{"动物":{“类型”:“狗”、“名称”:“花边”,“barkVolume”:0}}

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

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

然后让我们看看它是如何解开的动物园实例:

@Test public void whenDeserializingPolymorphic_thenCorrect() throws IOException {String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";Zoo Zoo = new objectapper () .readerFor(Zoo.class) .readValue(json);assertequal(“花边”,zoo.animal.name);assertequal (Zoo.Cat.class zoo.animal.getClass ());}

6.杰克逊一般注释

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

6.1。@jsonproperty.

我们可以添加@jsonproperty.注释指示JSON中的属性名称

让我们使用@jsonproperty.序列化/反统计财产名称当我们处理非标准的吸气器和定居者时:

public class MyBean {public int id;私人字符串名称;@jsonproperty(“name”)public void setthename(字符串名称){this.name = name;@jsonproperty(“name”)public string getthename(){返回名称;}}

接下来是我们的测试:

@Test public void whenUsingJsonProperty_thenCorrect() throws IOException {MyBean bean = new MyBean(1,“我的bean”);String result = new objectapper (). writevaleasstring (bean);为了(因此,containsString(“我的bean”));为了(因此,containsString (" 1 "));MyBean resultBean = new objectapper () .readerFor(MyBean.class) .readValue(result);assertequal(“我的豆”,resultBean.getTheName ());}

6.2。@jsonformat.

@jsonformat.annotation在序列化Date/Time值时指定一种格式。

在下面的例子中,我们使用@jsonformat.控制属性的格式活动日期

公共类EventWithFormat {公共字符串名称;@jsonformat(shape = jsonformat.shape.string,pattern =“dd-mm-yyyy hh:mm:ss”)公共日期eventdate;}

接下来是测试:

@Test公共void whenserializationusingjsonformat_thencorrect()抛出jsonprocessingException,parseexception {simpleDateFormat DF = New SimpleDateFormat(“DD-MM-YYYY HH:MM:SS”);df.settimezone(TimeZone.getTimeZone(“UTC”));字符串toparse =“20-12-2014 02:30:00”;日期日期= df.parse(toparse);EventWithFormat Event = New EventWithFormat(“派对”,日期);String结果= new objectMapper()。writevalueastring(事件);asserthat(结果,包含(Toparse));}

6.3。@JsonUnwrapped

@JsonUnwrapped定义在序列化/反序列化时应未包装/扁平的值。

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

公共类未包装用户{public int id;@jsonunwrape的公共名称名称;公共静态类名{公共字符串名字;公共字符串姓;}}

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

@test公共void whenserializationusingjsonunwrabled_thencorrect()抛出jsonprocessingException,parseexception {unwrappeduser.name name = new unwrappeduser.name(“John”,“Doe”);Unwrappyuser用户=新的未包装用户(1,名称);String结果= new objectMapper()。writevalueastring(用户);asserthat(结果,包含(“John”));asserthat(结果,不是(包含(“名称”))));}

最后,这是输出看起来的 - 静态嵌套类的字段与另一个字段一起包装的:

{“ID”:1,“FirstName”:“John”,“LastName”:“Doe”}

6.4。@jsonview.

@jsonview.表示将包含属性以用于序列化/反序列化的视图。

例如,我们将使用@jsonview.序列化的实例物品实体。

首先,让我们从观点开始:

public static class内部扩展public {}} public static class内部扩展public {}}

接下来这是物品使用视图的实体:

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

最后,全面测试:

@test public void whenserializationusingjsonview_thencorrect()抛出jsonprocessingexception {item项=新项目(2,“书”,“John”);String结果= new objectmapper().writerwithview(视图.public.class).writevalueastring(项目);asserthat(结果,包含(“书”));assertthat(结果,包含(“2”));assertthat(结果,不是(包含(“约翰”))));}

6.5。@JsonManagedReference, @JsonBackReference

@JsonManageReference.@jsonbackreference.注解可以处理父/子关系并在循环周围工作。

在下面的例子中,我们使用@JsonManageReference.@jsonbackreference.序列化我们itemwithref.实体:

public class ItemWithRef {public int id;公共字符串itemName;@JsonManagedReference public UserWithRef owner;}

我们的UserWithref.实体:

公共类userwithref {public int id;公共字符串名称;@jsonbackreference public list  userItems;}

然后测试:

@test public void whenserializationusingjacksonreferenceannotation_thencorrect()抛出jsonprocessingexception {userwithref user = new userwithref(1,“John”);itemwithref项目= new itemwithref(2,“书”,用户);user.additem(项目);String result = new objectapper (). writevaleasstring (item);asserthat(结果,包含(“书”));asserthat(结果,包含(“John”));asserthat(结果,不是(包含(“userItems”))));}

6.6。@jsonidentityinfo.

@jsonidentityinfo.表示在序列化/反序列化值时应该使用Object Identity,例如在处理无限递归类型的问题时。

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

@jsonidentityinfo(generator = objectidgenerators.propertygenerator.class,property =“id”)公共类inteptidistity {public int id;公共字符串itemName;公共用户无用手所有者;}

UserwithIdentity.实体:

@jsonidentityinfo(generator = objectidgenerators.propertygenerator.class,property =“id”)公共类userwithidentity {public int id;公共字符串名称;公共列表 UserItems;}

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

@test public void whenserializedusingjsonidentityinfo_thencorrect()抛出jsonprocessingexception {userwithidentity用户=新userwithidentity(1,“John”);ItemWithIdentity Item = New ItemWithIdentity(2,“书”,用户);user.additem(项目);String result = new objectapper (). writevaleasstring (item);asserthat(结果,包含(“书”));asserthat(结果,包含(“John”));assertthat(结果,containstring(“UserItems”));}

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

{" id ": 2,“itemName”:“书”,“主人”:{" id ": 1、“名称”:“约翰”,“userItems”:[2]}}

6.7。@jsonfilter.

@jsonfilter.注释指定在序列化期间使用的筛选器。

首先,我们定义实体,我们指向过滤器:

@JsonFilter("myFilter") public class BeanWithFilter {public int id;公共字符串名称;}

现在在完整的测试中,我们定义过滤器,除了除以除了所有其他属性之外名称从序列化:

@test public void whenserializationusingjsonfilter_thencorrect()抛出jsonprocessingexception {beanwithfilter bean = new beanwithfilter(1,“我的bean”);FilterProvider筛选器= new simplefilterprovider()。addfilter(“myfilter”,simplebeanpropertyfilter.filteroutallexcept(“名称”));string结果= new objectmapper().writer(筛选器).writevalueasstring(bean);为了(因此,containsString(“我的bean”));assertthat(结果,不是(包含(“ID”))));}

7.杰克逊自定义注释

接下来让我们看看如何创建自定义jackson注释。我们可以利用@JacksonAnnotationsInside注解:

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

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

@CustomAnnotation public class BeanWithCustomAnnotation {public int id;公共字符串名称;公共dateCreated日期;}

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

@test公共void whenserializationusingcustomannotation_thencorrect()抛出jsonprocessingException {beanwithcustomannotation bean = new beanwithcustomannotation(1,“my bean”,null);String result = new objectapper (). writevaleasstring (bean);为了(因此,containsString(“我的bean”));为了(因此,containsString (" 1 "));assertthat(结果,不是(包含(“datecreated”)))));}

序列化过程的输出:

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

8.杰克逊Mixin注释

接下来让我们看看如何使用jackson mixin注释。

例如,让我们使用MixIn注释忽略类型的属性用户

公共类项目{public int id;公共字符串itemName;公共用户所有者;}
@jsonignoretype public class mymixinforignoretype {}

那么让我们来看看这个是怎么运作的:

@Test public void whenSerializingUsingMixInAnnotation_thenCorrect() throws JsonProcessingException {Item Item = new Item(1, "book", null);String result = new objectapper (). writevaleasstring (item);为了(因此,containsString(“业主”));objectapper = new objectapper ();mapper.addMixIn (User.class MyMixInForIgnoreType.class);结果= mapper.writeValueAsString(项);为了(结果,而不是(containsString(“业主”)));}

9.禁用杰克逊注释

最后,让我们看看我们如何禁用所有Jackson注释.我们可以通过关闭MapperFeature。USE_ANNOTATIONS的示例如下:

@jsoninclude(include.non_null)@jsonpropertyorder({name“,”id“})公共类mybean {public int id;公共字符串名称;}

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

@test public void whendisabledallannotations_thenalldisabled()抛出IoException {MyBean Bean = New MyBean(1,Null);objectapper = new objectapper ();Mapper.Disable(mapperfeature.use_annotations);String结果= Mapper.WriteValueAstring(bean);为了(因此,containsString (" 1 "));asserthat(结果,包含(“名称”));}

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

{“ID”:1}

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

{“ID”:1,“名称”:null}

10.结论

在本文中,我们研究了Jackson注释,这只是对正确使用它们所能获得的灵活性的皮毛。

可以找到所有这些示例和代码片段的实现在GitHub

杰克逊底部

从Spring 5和Spring Boot 2开始学习春天课程:

>>查看课程
16评论
最老的
最新
内联反馈
查看所有评论
这篇文章的评论已经关闭!