introduction
Jackson, formerly known as hte standard JSON library for Java, or, as the "best JSON parser for Java", or simply as "JSON for Java.", more than that Jackson is a suite of data-processing tools for Java, including the flagship streaming[JOSON], etc...
以下内容翻译自baeldung
概括
这篇文章将带你深入Jackson Annotations并学习如何使用这些Annotations、 如何创建自定义的注解, 并且如何禁用它们。
Jaskson Serialization Annotations( Jackson 序列化注解 )
@JsonAnyGetter
这个注解允许使用Map灵活输出属性,下面是代码片段——ExtendableBean 类有一个 name 属性 和一个可拓展的 key/value 格式的属性。
public class ExtendableBean {
public String name;
public Map properties;
@JsonAnyGetter
public Map getProperties() {
return properties
}
}
当我们序列化这个实体的实例的时候,我们将得到所有Map中 key-values ,并以标准的形式输出:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
实践代码:
@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"));
}
同样的, 我们可以使用可选参数 enabled
,传入false
禁用 @JsonAnyGetter, 本例中,序列化后的 Map 将会转化为Json格式的 properties 变量。
@JsonGetter
@JsonGetter 注解作为 @JsonProperty 注解的代替, 作用是将一个方法标记为 getter 方法。
下面这个实例中,我们指定名为getTheName()
方法作为 Mybean 实体中 name
属性的 getter 方法。
public class MyBean {
public int id;
private String name;
@JsonGetter("name")
public String getTheName() {
return name;
}
}
实践代码:
@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"));
}
@JsonPropertyOrder
用以指定Json序列化顺序, 自定义属性顺序代码:
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
@JsonRawValue
用以命令 Jackson 原原本本地序列化一个属性。
public class RawBean {
public String name;
@JsonRawValue
public String json;
}
以上代码将会输出以下格式
{
"name":"My bean",
"json":{
"attr":false
}
}
@JsonValue
被 @JsonValue
标识地方法会被Jackson库用于序列化整个对象实例,
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
// standard constructors
@JsonValue
public String getName() {
return name;
}
}
例如,在枚举类型中,我们使用 @JsonValue 注解 getName 方法, 整个实体将会被序列化为它的 name 属性
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;
}
}
@JsonRootName
当启用Wrapping的时候, @JsonRootName 注解用于指定根 Wrapper 的名字。
Wrapping 指的是, 例如一个 User 实例原本序列化为以下格式:
{
"id": 1,
"name": "John"
}
启用被 Wrapped 后将变成以下格式:
{
"User": {
"id": 1,
"name": "John"
}
}
案例: 使用 @JsonRootName 指定一个隐式的Wrapper 实体的名字 :
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
一般情况下, Wrapper的名字是类的名字 - UserWithRoot, 使用这个注解后,我们会得到更简洁的类名字。
@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"));
}
输出:
{
"user":{
"id":1,
"name":"John"
}
}
tip: Jackson 2.4以后, 一个新的可选参数namespace
可用, 该选项用于像是XML的数据格式。 如果我们加上这个参数,那么其指定的值将成为一个完全合法的名字。
@JsonRootName(value = "user", namespace="users")
public class UserWithRootNamespace {
public int id;
public String name;
// ...
}
使用XmlMapper 对其序列化,将会输出以下格式:
1
John
@JsonSerialize
@JsonSerialize 指定一个自定义序列化器, 用于序列化一个实体。
快速示例——使用@JsonSerialize 指定CustomDateSerilizer 类序列化eventDate属性。
public class EventWithSerializer {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
CustomDateSerilizer 序列化器参考实现:
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));
}
}
反序列注解
@JsonCreator
用于调整用于反序列的构造函数/工厂。
当我们需要序列化一些并不需要完全匹配目标实体的JSON的时候,可以用 @JsonCreator 注解
假设我们需要反序列下面这个JSON:
{
"id":1,
"theName":"My bean"
}
然而目标实体只有name而并没有theName字段。 在不改变实体的前提下,我们需要对反序列过程更大程度的控制——用@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;
}
}
@JacksonInject
@JacksonInject 标识一个属性将被注入其值,而非从JSON数据。
对id 属性进行注入:
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
}
@JsonAnySetter
@JsonAnySetter 允许使用 Map 灵活加入属性。 在反序列化过程中, JSON中的属性会轻松地加入到map中。
使用@JsonAnySetter 反序列化实体类 EntendableBean:
public class ExtendableBean {
public String name;
private Map properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
输出:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
译者:结合 @JsonAnyGetter 加深印象
@JsonSetter
@JsonSetter 作为@JsonProperty地替代——将一个方法标记为setter。
当我们需要读取JSON数据但是目标实体类并不能完全匹配对应字段的时候, 这个注解将非常有用。
下面这个示例指定MyBean 实体类中的 setTheName()
作为 name 属性的 setter 。
public class MyBean {
public int id;
private String name;
@JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
@JsonDeserialize
@JsonDeserialize 标志一个自定义反向序列器
示例, 使用@JsonDeserialize 标志 CustomDateDeserializer 作为 eventDate 属性的反向序列器:
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);
}
}
}
@JsonAlias
@JsonAlias 在反序列过程中为属性定义一个或多个别名
示例:
public class AliasBean {
@JsonAlias({ "fName", "f_name" })
private String firstName;
private String lastName;
}
在以上的POJO, Jackson库将JSON中带有诸如 fName, f_name, firstName 的字段反序列化到firstName 变量中。
Jackson Property Inclusion Annotations(Jackson 包含注解)
@JsonIgnoreProperties
@JsonIgnoreProperties 是一个类级别的注解, 它标记一个属性或者一个属性列表,被标记的属性或属性列表将会被忽略输出
示例, 从序列化中忽略id属性
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
@JsonIgnore
@JsonIgnore 注解用于标记一个字段级别的属性。
示例, 在序列化中忽略id属性
public class BeanWithIgnore {
@JsonIgnore
public int id;
public String name;
}
@JsonIgnoreType
@JsonIgnoreType 将忽略所有被注解的属性类型
示例, 忽略所有类型为Name的属性
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
@JsonInclude
使用 @JsonInclude
排除empty/null/default的值
示例, 序列化中排除所有null 值
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
@JsonAutoDetect
使用@JsonAutoDtect覆盖默认语义下的属性可见性。
示例,启用序列化私有属性
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}
Jackson Polymorphic Type Handling Annotations(Jackson 多态类型处理注解)
*@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;
}
}
测试代码:
@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"));
}
输出:
{
"animal": {
"type": "dog",
"name": "lacy",
"barkVolume": 0
}
}
使用以下JSON类型对实体类反序列化:
{
"animal":{
"name":"lacy",
"type":"cat"
}
}
反序列获得Zoo示例代码:
@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());
}