目录
- @JsonProperty (序列化/反序列化)
- @JsonPropertyOrder(序列化)
- @JsonFormat(序列化/反序列化)
- @JsonRawValue(序列化)
- @JsonValue(序列化)
- @JsonRootName(序列化)
- @JsonCreator(反序列化)
- @JacksonInject(反序列化)
- @JsonAlias(反序列化)
- @JsonGetter 与 @JsonSetter
- @JsonAnyGetter 与 @JsonAnySetter
- @JsonSerialize 与 @JsonDeserialize
- 属性包含注释
- @JsonUnwrapped(序列化/反序列化)
- @JsonView
- 多态类型处理注释
- @JsonManagedReference 与 @JsonBackReference
- @JsonIdentityInfo
- @JsonFilter(序列化)
@JsonProperty (序列化/反序列化)
@JsonProperty注解用于属性或方法上,作用是把该属性的名称序列化为另外一个名称。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyBean {
private int id;
@JsonProperty("n")
private String name;
}
@Test
public void whenUsingJsonProperty_thenCorrect()
throws IOException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
MyBean resultBean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(result);
System.out.println(resultBean);
}
结果:
{“id”:1,“n”:“My bean”}
MyBean(id=1, name=My bean)
@JsonPropertyOrder(序列化)
我们可以使用@JsonPropertyOrder注解来指定序列化的属性顺序。
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonPropertyOrder({"name", "id"})
public class MyBean {
private int id;
private String name;
}
序列化输出结果将按照指定顺序输出:
{“name”:“My bean”,“id”:1}
@JsonFormat(序列化/反序列化)
@JsonFormat注释指定序列化日期/时间值时的格式。
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd hh:mm:ss")
private Date eventDate;
@JsonRawValue(序列化)
@JsonRawValue注释可以指示Jackson按原样序列化属性。 直接显示属性值,对字符串,即是去掉双引号。
public class RawBean {
private String name;
@JsonRawValue
private String json;
}
加注解输出:
{“name”:“My bean”,“json”:{“attr”:false}}
不加注解输出:
{“name”:“My bean”,“json”:"{“attr”:false}"}
@JsonValue(序列化)
@JsonValue注解用于序列化整个实例的单个方法。可以用在get方法或者属性字段上,一个类只能用一个,当加上@JsonValue注解是,序列化是只返回这一个字段的值。
例如,实体类中age属性加上注解
@JsonValue
private Integer age;
序列化这个类时,只返回了age的值:
25
@JsonRootName(序列化)
如果启用了包装,则使用@JsonRootName注解来指定要使用的根包装的名称。包装意味着不是将用户序列化为:
{
"id": 1,
"name": "John"
}
它将被包装成这样:
{
"User": {
"id": 1,
"name": "John"
}
}
@JsonRootName(value = "user")
public class UserWithRoot {
private int id;
private String name;
}
@JsonCreator(反序列化)
在反序列化时,Jackson默认会调用对象的无参构造函数,如果我们不定义任何构造函数,Jvm会负责生成默认的无参构造函数。但是如果我们定义了构造函数,并且没有提供无参构造函数时,Jackson会报错。
@JsonCreator注解用在对象的反序列时指定特定的构造函数或者工厂方法。如果默认构造函数无法满足需求,或者说我们需要在构造对象时做一些特殊逻辑,可以使用该注解。该注解需要搭配@JsonProperty使用。
@Data
public class BeanWithCreator {
private int id;
private 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);
}
@JacksonInject(反序列化)
@JacksonInject表示属性将从注入而不是从JSON数据获取其值。
应用场景: 假设json字段有一些缺少的属性,抓换成实体类的时候没有的属性将为null,但是我们在某些需求当中需要将为null的属性都设置为默认值,这时候我们就可以用到这个注解了,它的功能就是在反序列化的时候将没有的字段设置为我们设置好的默认值。
@Data
public class BeanWithInject {
@JacksonInject
private int id;
private String name;
}
@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);
System.out.println(bean);
}
@JsonAlias(反序列化)
@JsonAlias在反序列化期间为属性定义一个或多个可选名称。
@Data
public class AliasBean {
@JsonAlias({"fName", "f_name"})
private String firstName;
private String lastName;
}
@Test
public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";
AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
Assertions.assertEquals("John", aliasBean.getFirstName());
}
@JsonGetter 与 @JsonSetter
@JsonGetter注解是@JsonProperty注解的替代方法,标记为getter方法上。
@JsonSetter注解是@JsonProperty注解的替代方法,标记为setter方法上。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyBean {
private int id;
private String name;
@JsonGetter("n")
public String getName() {
return name;
}
@JsonSetter("n")
public void setName(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);
}
@Test
public void whenDeserializingUsingJsonSetter_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"n\":\"My bean\"}";
MyBean bean = new ObjectMapper()
.readerFor(MyBean.class)
.readValue(json);
System.out.println(bean);
}
@JsonAnyGetter 与 @JsonAnySetter
@JsonAnyGetter注解允许灵活地将 Map 字段用作标准属性。
**应用场景:**主要用来获取序列化时未匹配上的字段。
注意事项:
(1)用于非静态无参方法,方法名随意;
(2)方法返回值必须是Map类型;
(3)在一个实体类中仅仅用在一个方法上;
(4)序列化的时候json字段的key就是返回Map的key,value就是Map的value。
@JsonAnySetter允许我们灵活地使用Map作为标准属性。
**应用场景:**主要用于反序列化时,JSON中的属性将简单地添加到映射中,一般将对应不上的字段全部放到Map里面。
注意事项:
(1)用于非静态无参方法,注解的方法必须有两个参数,第一个是json字段中的key,第二个是value,方法名随意;
(2)也可以用在Map对象属性上面。
示例:ExtendableBean实体类具有name属性和一组键/值对形式的可扩展属性properties:
以下示例都使用了 Lomback 插件,Lomback使用示例可以参考连接
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class ExtendableBean {
@NonNull
private String name;
private Map<String, String> properties;
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
@JsonAnySetter
public void add(String v1, String v2) {
if (properties == null) {
properties = new HashMap<>();
}
properties.put(v1, v2);
}
}
@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);
System.out.println(result);
}
@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);
System.out.println(bean);
}
当序列化此实体的实例时,会将映射中的所有键值作为标准的普通属性,可以看出加上这个注解以后序列化的时候就会将Map里面的值也相当于实体类里面的字段给显示出来了:
{“name”:“My bean”,“attr2”:“val2”,“attr1”:“val1”}
当反序列化时,attr1和attr2将被加入map类型的属性中:
ExtendableBean{name=‘My bean’, properties={attr2=val2, attr1=val1}}
@JsonSerialize 与 @JsonDeserialize
@JsonSerialize表示在封送实体时要使用的自定义序列化程序。
@JsonDeserialize指示使用自定义反序列化程序。
应用场景: 当需要自定义序列化反序列化格式时可以使用。
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class EventWithSerializer {
private String name;
@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date eventDate;
}
public class CustomDateSerializer extends StdSerializer<Date> {
private static final SimpleDateFormat FORMATTER
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize(
Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException {
gen.writeString(FORMATTER.format(value));
}
}
public class CustomDateDeserializer
extends StdDeserializer<Date> {
private static final 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);
}
}
}
属性包含注释
@JsonIgnoreProperties
@JsonIgnoreProperties是一个类级别的注释,用于标记Jackson将忽略的属性或属性列表。
@Data
@JsonIgnoreProperties({"id"})
public class BeanWithIgnore {
private int id;
private String name;
}
@JsonIgnore
@JsonIgnore注解用于在字段级别标记要忽略的属性。
@Data
public class BeanWithIgnore {
@JsonIgnore
private int id;
private String name;
}
@JsonIgnoreType
@JsonIgnoreType将注释类型的所有属性标记为忽略。
@Data
@AllArgsConstructor
public class User {
private int id;
private Name name;
@Data
@AllArgsConstructor
@JsonIgnoreType
public static class Name {
private String firstName;
private String lastName;
}
}
@Test
public void whenSerializingUsingJsonIgnoreType_thenCorrect()
throws JsonProcessingException {
User.Name name = new User.Name("John", "Doe");
User user = new User(1, name);
String result = new ObjectMapper()
.writeValueAsString(user);
System.out.println(result);
}
序列化将忽略name属性,得到:
{“id”:1}
@JsonInclude
我们可以使用@JsonInclude排除具有 empty/null/默认值的属性。
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyBean {
private int id;
private String name;
}
@Test
public void whenSerializingUsingJsonInclude_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, null);
String result = new ObjectMapper()
.writeValueAsString(bean);
System.out.println(result);
}
序列化将忽略null值属性,得到:
{“id”:1}
@JsonAutoDetect
@JsonAutoDetect可以覆盖哪些属性可见哪些属性不可见的默认语义。
@NoArgsConstructor
@AllArgsConstructor
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean {
private int id;
private String 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);
}
私有属性在没有getter方法的情况下依然可以序列化:
{“id”:1,“name”:“My bean”}
@JsonUnwrapped(序列化/反序列化)
@JsonUnwrapped定义序列化/反序列化时应展开/展平的值。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UnwrappedUser {
private int id;
@JsonUnwrapped
private Name name;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Name {
private String firstName;
private String 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”}
不加注解输出:
{“id”:1,“name”:{“firstName”:“John”,“lastName”:“Doe”}}
@JsonView
@JsonView指示将在其中包含属性以进行序列化/反序列化的视图。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Item {
@JsonView(Views.Public.class)
private int id;
@JsonView(Views.Public.class)
private String itemName;
@JsonView(Views.Internal.class)
private 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 result1 = new ObjectMapper()
.writerWithView(Views.Internal.class)
.writeValueAsString(item);
System.out.println(result1);
}
不同视图输出不同的属性:
{“id”:2,“itemName”:“book”}
{“id”:2,“itemName”:“book”,“ownerName”:“John”}
多态类型处理注释
@JsonTypeInfo
@JsonTypeInfo指示序列化中要包含的类型信息的详细信息
@JsonSubTypes
@JsonSubTypes表示带注释类型的子类型
@JsonTypeName
@JsonTypeName定义用于注释类的逻辑类型名称
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Zoo {
private Animal animal;
@Data
@NoArgsConstructor
@AllArgsConstructor
@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 {
private String name;
}
@Data
@NoArgsConstructor
@JsonTypeName("dog")
public static class Dog extends Animal {
private double barkVolume;
public Dog(final String name) {
super(name);
}
}
@Data
@NoArgsConstructor
@JsonTypeName("cat")
public static class Cat extends Animal {
private boolean likesCream;
private int lives;
public Cat(final String name) {
super(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);
}
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
Zoo zoo = new ObjectMapper()
.readerFor(Zoo.class)
.readValue(json);
System.out.println(zoo);
}
下面是用Dog序列化Zoo实例的结果:
{“animal”:{“type”:“dog”,“name”:“lacy”,“barkVolume”:0.0}}
反序列化结果:
Zoo(animal=Zoo.Cat(likesCream=false, lives=0))
@JsonManagedReference 与 @JsonBackReference
@JsonManagedReference和@JsonBackReference注释可以处理父/子关系并绕过循环。
这两个标注通常配对使用,通常用在父子关系中。@JsonBackReference标注的属性在序列化时,会被忽略(即结果中的json数据不包含该属性的内容)。@JsonManagedReference标注的属性则会被序列化。在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。但在反序列化时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class UserWithRef {
@NonNull
private int id;
@NonNull
private String name;
@JsonBackReference
private List<ItemWithRef> userItems;
public void addItem(ItemWithRef itemWithRef) {
if (userItems == null) {
userItems = new ArrayList<>();
}
userItems.add(itemWithRef);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ItemWithRef {
private int id;
private String itemName;
@JsonManagedReference
private UserWithRef owner;
}
@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);
}
@JsonIdentityInfo
@JsonIdentityInfo指出在序列化/反序列化值时应该使用对象标识,例如在处理无限递归类型的问题时。
@Data
@AllArgsConstructor
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
private int id;
private String itemName;
private UserWithIdentity owner;
}
@Data
@RequiredArgsConstructor
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class UserWithIdentity {
@NonNull
private int id;
@NonNull
private String name;
private List<ItemWithIdentity> userItems;
public void addItem(ItemWithIdentity itemWithIdentity) {
if (userItems == null) {
userItems = new ArrayList<>();
}
userItems.add(itemWithIdentity);
}
}
@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]}}
@JsonFilter(序列化)
@JsonFilter注释指定序列化期间要使用的过滤器。
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonFilter("myFilter")
public class BeanWithFilter {
private int id;
private String name;
}
@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);
System.out.println(result);
}