在本文中,我们将深入探讨Jackson注解。
我们将看到如何使用Jackson现有的注解,如何创建自定义注解以及如何禁用它们。
@JsonAnyGetter注解提供了将Map字段转换为标准属性的灵活性。这是一个简单的示例– ExtendableBean实体具有name属性和一组以K/V对形式的可扩展属性:
public class ExtendableBean {
public String name;
private Map<String, String> properties;
public ExtendableBean() {
properties = new HashMap<String, String>();
}
public ExtendableBean(final String name) {
this.name = name;
properties = new HashMap<String, String>();
}
@JsonAnySetter
public void add(final String key, final String value) {
properties.put(key, value);
}
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
}
序列化此实体的实例时,我们将Map中的所有键值作为标准的纯属性获取,如下:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
测试:
@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect() throws JsonProcessingException {
final ExtendableBean bean = new ExtendableBean("My bean");
bean.add("attr1", "val1");
bean.add("attr2", "val2");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
我们还可以使用启用为false的可选参数来禁用@JsonAnyGetter()。在这种情况下,地图将转换为JSON,并在序列化后显示在properties变量下。{"name":"My bean","properties":{"attr2":"val2","attr1":"val1"}}
@JsonGetter注解是@JsonProperty注解的替代方法,用于将方法标记为getter方法。
在以下示例中,我们将方法getTheName()指定为MyBean实体的name属性的getter方法:
public class MyBean {
private int id;
private String name;
public MyBean() {
}
public MyBean(final int id, final String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@JsonGetter("name")
public String getTheName() {
return name;
}
@JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
测试:
@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
// {"id":1,"name":"My bean"}
因为这里
name
属性是私有的,且get和set方法名不是使用get/set+属性名。而jackson在序列化的时候,如果是私有属性会调用它的get方法,默认的get方法名就是get+属性名
。如果不使用@JsonGetter注解指定,jackson会认为theName是一个属性。输出如下:
{"id":1,"theName":"My bean"}
我们可以使用@JsonPropertyOrder注解指定序列化属性的顺序。让我们为MyBean实体的属性设置自定义顺序:
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
测试输出如下:
{"name":"My bean","id":1}
我们还可以使用@JsonPropertyOrder(alphabetic = true)
按字母顺序对属性进行排序。在这种情况下,序列化的输出将是:{"id":1,"name":"My bean"}
@JsonRawValue注解可以使Jackson完全按原样序列化属性。
在以下示例中,我们使用@JsonRawValue嵌入一些自定义JSON作为实体的值:
public class RawBean {
public String name;
@JsonRawValue
public String json;
public RawBean() {}
public RawBean(final String name, final String json) {
this.name = name;
this.json = json;
}
}
测试:
@Test
public void whenSerializingUsingJsonRawValue_thenCorrect() throws JsonProcessingException {
final RawBean bean = new RawBean("My bean", "{\"attr\":false}");
final String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
// {"name":"My bean","json":{"attr":false}}
// 如果不加@JsonRawValue注解;输出为:{"name":"My bean","json":"{\"attr\":false}"}
我们还可以使用可选的布尔参数值(value)来定义此注解是否起作用。
@JsonValue注解的作用是告诉jackson序列化类实例时使用它标注的的单个方法。
例如,在一个枚举中,我们用@JsonValue注释getName,以便任何这样的实体都通过其名称序列化:
public enum TypeEnumWithValue {
TYPE1(1, "Type A"),
TYPE2(2, "Type 2");
private Integer id;
private String name;
TypeEnumWithValue(Integer id, String name) {
this.id = id;
this.name = name;
}
@JsonValue
public String getName() {
return name;
}
}
测试:
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
throws JsonParseException, IOException {
String enumAsString = new ObjectMapper()
.writeValueAsString(TypeEnumWithValue.TYPE1);
System.out.println(enumAsString);
}
// "Type A"
如果不使用@JsonValue标记,枚举序列化出来的是"TYPE1"
@JsonRootName的作用可以理解为,在序列化好的json串外面再包裹一层。
假设之前我们的序列化之后是这样的:{ "id": 1, "name": "John" }
使用@JsonRootName包裹一层会变成这样
{ "user": { "id": 1, "name": "John" } }
看一下如何使用:
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
从Jackson 2.4开始,新的可选参数名称空间可用于XML等数据格式。如果添加它,它将成为完全限定名称的一部分:
@JsonRootName(value = "user", namespace="users")
public class UserWithRootNamespace {
public int id;
public String name;
// ...
}
xml效果是这样的
<user xmlns="users">
<id xmlns="">1id>
<name xmlns="">Johnname>
<items xmlns=""/>
user>
@JsonSerialize表示在序列化实体时要使用的自定义序列化程序。
让我们看一个简单的例子。我们将使用@JsonSerialize通过CustomDateSerializer来序列化eventDate属性:
public class EventWithSerializer {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
这是简单的自定义Jackson序列化器:
public class CustomDateSerializer extends StdSerializer<Date> {
private static final long serialVersionUID = -2894356342227378312L;
private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(final Class<Date> t) {
super(t);
}
@Override
public void serialize(Date date,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(formatter.format(date));
}
}
让我们测试下:
@Test
public void whenSerializingUsingJsonSerialize_thenCorrect()
throws JsonProcessingException {
Date date = new Date();
EventWithSerializer event = new EventWithSerializer("party", date);
String result = new ObjectMapper().writeValueAsString(event);
System.out.println(result);
}
// {"name":"party","eventDate":"24-02-2020 02:34:26"}
我们可以使用@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;
}
}
测试
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"theName\":\"My bean\"}";
BeanWithCreator bean = new ObjectMapper()
.readerFor(BeanWithCreator.class)
.readValue(json);
System.out.println(bean.name);
}
// My bean
// 如果不使用,会报错。
@JacksonInject表示该属性将从注入中获取而不是从JSON数据获取其值。
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
public BeanWithInject() {
}
public BeanWithInject(final int id, final String name) {
this.id = id;
this.name = name;
}
}
测试如下:
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws IOException {
String json = "{\"name\":\"My bean\"}";
// 使用jackson的InjectableValues类进行注入
InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper()
.reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
System.out.println(bean);
}
// BeanWithInject{id=1, name='My bean'}
@JsonAnySetter使我们可以灵活地使用Map作为标准属性。反序列化时,JSON的属性将简单地添加到地图中。和之前介绍的@JsonAnyGetter正好相反。
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
假设我们的json是这样的:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
那么
attr2
和attr1
会注入到Map中。
和之前介绍的@JsonGetter相反,不做过多介绍。
这个是用来指定自定义的反序列化规则的。
让我们来看一个例子,我们将使用@JsonDeserialize与CustomDateDeserializer反序列化eventDate属性:
public class EventWithSerializer {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
自定义的反序列化器:
public class CustomDateDeserializer extends StdDeserializer<Date> {
private static final long serialVersionUID = -5451717385630622729L;
private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(final Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
final String date = jsonParser.getText();
try {
return formatter.parse(date);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
测试:
@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
throws IOException {
String json = "{\"name\":\"party\",\"eventDate\":\"02-02-2020 02:30:00\"}";
EventWithSerializer event = new ObjectMapper()
.readerFor(EventWithSerializer.class)
.readValue(json);
System.out.println(event);
}
// EventWithSerializer{name='party', eventDate=Sun Feb 02 02:30:00 CST 2020}
@JsonAlias在反序列化期间为属性定义一个或多个备用名称。
让我们用一个简单的例子看看这个注解是如何工作的:
public class AliasBean {
@JsonAlias({ "fName", "f_name" })
private String firstName;
private String lastName;
}
在这里,我们有一个POJO,我们想将JSON中的fName、f_name或firstName属性的值反序列化到POJO的firstName变量中。
测试如下:
@Test
public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";
AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
System.out.println(aliasBean);
}
// AliasBean{firstName='John', lastName='Green'}
@JsonIgnoreProperties是一个类级别的注解,用于标记Jackson将忽略的一个属性或一系列属性。
让我们看一个简单的示例,忽略序列化中的属性ID:
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
@JsonIgnore批注用于在字段级别标记要忽略的属性。
public class BeanWithIgnore {
@JsonIgnore
public int id;
public String name;
}
@JsonIgnoreType将带注解类的所有属性标记为忽略。
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
我们可以使用@JsonInclude排除具有
empty/null/default values
的属性。
// 从序列化中排除空值:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
@JsonAutoDetect可以覆盖默认语义,即哪些属性可见,哪些属性不可见。
让我们来看一个简单的示例,该注解如何帮助我们让私有属性可序列化:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
public PrivateBean() {}
public PrivateBean(final int id, final String name) {
this.id = id;
this.name = name;
}
}
测试:
@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
throws JsonProcessingException {
PrivateBean bean = new PrivateBean(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
System.out.println(result);
}
// {"id":1,"name":"My bean"}
这样,私有属性没有get方法也可以被序列化了。
接下来–让我们看一下Jackson的多态类型处理注释:
- @JsonTypeInfo - 指示要在序列化中包含哪些类型信息的详细信息
- @JsonSubTypes - 指示带注解类型的子类型
- @JsonTypeName - 定义用于注解类的逻辑类型名称
让我们看一个复杂的示例,使用@JsonTypeInf
o,@ JsonSubTypes
和@JsonTypeName
三个注解序列化和反序列化实体Zoo
:
public class Zoo {
public Animal animal;
public Zoo() {}
public Zoo(final Animal animal) {
this.animal = animal;
}
/***********************以下是三个静态内部类*********************/
public static class Animal {
public String name;
public Animal() {}
public Animal(final String name) {
this.name = name;
}
}
public static class Dog extends Animal {
public double barkVolume;
public Dog() {}
public Dog(final String name) {
this.name = name;
}
}
public static class Cat extends Animal {
boolean likesCream;
public int lives;
public Cat() {}
public Cat(final String name) {
this.name = name;
}
}
}
以上我们什么注解都没有加,看序列化后是什么结果
@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);
System.out.println(result);
}
// {"animal":{"name":"lacy","barkVolume":0.0}}
这样序列化后,我们只知道是一个动物,却不知道具体是什么动物,下面我们就利用以上三个注解进行修饰下。
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.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;
public Animal() {}
public Animal(final String name) {
this.name = name;
}
}
@JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
public Dog() {}
public Dog(final String name) {
this.name = name;
}
}
@JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
public Cat() {}
public Cat(final String name) {
this.name = name;
}
}
我们在
Animal
类上加上以上注解,再看一下序列化后的结果
{"animal":{"type":"dog","name":"lacy","barkVolume":0.0}}
我们发现为我们多加了一个type
属性。
下面试一下反序列化
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
// {"animal":{"name":"lacy","type":"cat","likesCream":false,"lives":2}}
Zoo zoo = new ObjectMapper()
.readerFor(Zoo.class)
.readValue(json);
assertEquals("lacy", zoo.animal.name);
assertEquals(Zoo.Cat.class, zoo.animal.getClass());
}
// 可以正常执行通过。
如果将
String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
改为String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"dog\"}}";
就会报错。
我们可以添加@JsonProperty注解在JSON中指示属性名称。可以看做是@JsonGetter和@JsonSetter的组合版
在处理非标准的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;
}
}
@JsonFormat注解指定序列化时间类型的格式。
public class EventWithFormat {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}
经测试,@JsonFormat
对java8新增的时间类型LocalDateTime等,不适用。
@JsonUnwrapped定义在序列化/反序列化时应该解包/展平的值。
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public UnwrappedUser() {}
public UnwrappedUser(final int id, final Name name) {
this.id = id;
this.name = name;
}
public static class Name {
public String firstName;
public String lastName;
public Name() {
}
public Name(final String firstName, final String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
}
序列化测试:
@Test
public void whenSerializingUsingJsonUnwrapped_thenCorrect()
throws JsonProcessingException {
UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
UnwrappedUser user = new UnwrappedUser(1, name);
String result = new ObjectMapper().writeValueAsString(user);
System.out.println(result);
}
// {"id":1,"firstName":"John","lastName":"Doe"}
反序列化测试:
@Test
public void whenDeserializingUsingJsonUnwrapped_thenCorrect()
throws JsonProcessingException {
String json = "{\"id\":1,\"firstName\":\"John\",\"lastName\":\"Doe\"}";
String json1 = "{\"id\":1,\"name\":{\"firstName\":\"John\",\"lastName\":\"Doe\"}}";
UnwrappedUser bean = new ObjectMapper()
.readerFor(UnwrappedUser.class)
.readValue(json1);
assertEquals("John",bean.name.firstName);
}
// 经测试,json1形式的反序列化后,name属性是没有值的,所以使用@JsonUnwrapped注解后,反序列化时需要注意
@JsonView表示包含用于序列化/反序列化的属性的视图。也就是我们可以通过@JsonView的方式指定需要序列化那些属性。
// 定义一个视图类
public class Views {
public static class Public {}
public static class Internal extends Public {}
}
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
测试如下:
@Test
public void whenSerializingUsingJsonView_thenCorrect()
throws JsonProcessingException {
Item item = new Item(2, "book", "John");
String result = new ObjectMapper()
.writerWithView(Views.Public.class)
.writeValueAsString(item);
System.out.println(result);
String result2 = new ObjectMapper()
.writerWithView(Views.Internal.class)
.writeValueAsString(item);
System.out.println(result2);
}
/*
{"id":2,"itemName":"book"}
{"id":2,"itemName":"book","ownerName":"John"}
*/
@JsonManagedReference和@JsonBackReference可以解决嵌套关系和循环问题
首先先看这么两个类
public class ItemWithRef {
public int id;
public String itemName;
public UserWithRef owner;
}
public class UserWithRef {
public int id;
public String name;
public List<ItemWithRef> userItems;
}
这两个类中的属性都有各自的属性。假设我们不做约束,看看序列化会有什么结果
@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);
System.out.println(result);
}
// 此时会报错会报一个很长很长的错误。这里就不贴出来了。
我们为两个类加上上面两个注解再试一次,看看会怎么样
public class ItemWithRef {
public int id;
public String itemName;
@JsonManagedReference
public UserWithRef owner;
}
public class UserWithRef {
public int id;
public String name;
@JsonBackReference
public List<ItemWithRef> userItems;
}
这次就可以正常序列化了{"id":2,"itemName":"book","owner":{"id":1,"name":"John"}}
**注意:**直接序列化那个对象的属性上标注
@JsonManagedReference
@JsonIdentityInfo表明在序列化/反序列化时应该使用对象标识——例如,处理无限递归类型的问题。
看下面类似6.5的例子
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class UserWithIdentity {
public int id;
public String name;
public List<ItemWithIdentity> userItems;
}
测试如下:
@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);
System.out.println(result);
}
// {"id":2,"itemName":"book","owner":{"id":1,"name":"John","userItems":[2]}}
/*
{
"id": 2,
"itemName": "book",
"owner": {
"id": 1,
"name": "John",
"userItems": [
2
]
}
}
*/
注意:这里的结果和6.5中的不一样哦
- 6.5中
owner
属性中少了userItems
属性- 这里
owner
属性中的userItems
中使用id来标识。
@JsonFilter注解指定在序列化期间使用的过滤器。
看一个例子:
@JsonFilter("myFilter")
public class BeanWithFilter {
public int id;
public String name;
}
序列化时:
@Test
public void whenSerializingUsingJsonFilter_thenCorrect()
throws JsonProcessingException {
BeanWithFilter bean = new BeanWithFilter(1, "My bean");
// 这里添加了一个名为`myFilter`的过滤器,作用是:除了`name`属性,其他的都排除在外
FilterProvider filters
= new SimpleFilterProvider().addFilter(
"myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name"));
String result = new ObjectMapper()
.writer(filters)
.writeValueAsString(bean);
System.out.println(result);
}
// {"name":"My bean"}
接下来,让我们看看如何创建自定义Jackson注解。这里我们需要使用@JacksonAnnotationsInside注解:
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {}
// 说是自定义,其实就是使用Jackson原有的注解,将其进行组合,这个注解的作用:忽略空值属性,并按照"name", "id", "dateCreated"排序。
使用
@CustomAnnotation
public class BeanWithCustomAnnotation {
public int id;
public String name;
public Date dateCreated;
}
测试下:
@Test
public void whenSerializingUsingCustomAnnotation_thenCorrect()
throws JsonProcessingException {
BeanWithCustomAnnotation bean
= new BeanWithCustomAnnotation(1, "My bean", null);
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
/*
{
"name":"My bean",
"id":1
}
*/
看下面的例子
public class Item2 {
public int id;
public String itemName;
public User owner;
}
@JsonIgnoreType
public class MyMixInForIgnoreType {}
序列化时:
@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect()
throws JsonProcessingException {
User u = new User(2,"John");
Item2 item = new Item2(1, "book", u);
String result = new ObjectMapper().writeValueAsString(item);
System.out.println(result);
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(User.class, MyMixInForIgnoreType.class); // 将User列为忽略的类型
String result2 = mapper.writeValueAsString(item);
System.out.println(result2);
}
/*
{"id":1,"itemName":"book","owner":{"id":2,"name":"John"}}
{"id":1,"itemName":"book"}
*/
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
// 这样就禁用了注解
看一个例子
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
MyBean bean = new MyBean(1, null);
如果不禁用注解序列化为:
{"id":1}
禁用注解后的结果为:
{
"id":1,
"name":null
}