在 Jackson 库中,有多个注解和扩展点来支持我们个性化的序列化和反序列化需求。下面我们来做一个总结,建议收藏备用。
目录
- 1️⃣Jackson中的常用注解
- 1 @JsonSerialize 和 @JsonDeserialize
- 2 @JsonProperty
- 3 @JsonIgnore
- 4 @JsonFormat
- 5 @JsonUnwrapped
- 6 @JsonAnyGetter
- 7 @JsonInclude
- 8 @JsonAlias
- 9 @JsonIgnoreProperties
- 10 @JsonManagedReference 和 @JsonBackReference
- 11 @JsonCreator
- 12 @JsonTypeInfo
- 13 @JsonFilter
- 14 @JsonAnySetter
- 15 @JsonAppend
- 16 @JsonIgnoreType
- 17 @JsonGetter 和 @JsonSetter
- 18 @JsonPropertyOrder
- 2️⃣Jackson 库中的模块
- 3️⃣ Jackson 库的扩展点
1️⃣Jackson中的常用注解
1 @JsonSerialize 和 @JsonDeserialize
用于自定义序列化和反序列化过程中的操作,它们的作用如下:
1.1 @JsonSerialize 注解
用于指定一个自定义的序列化器,将 Java 对象转换为 JSON 字符串。
通过在属性、getter 方法或类级别上使用 @JsonSerialize 注解,可以指定要使用的序列化器。
这使得你可以控制如何将对象转换为 JSON 字符串,包括自定义字段值的格式、类型转换等。
1.2 @JsonDeserialize 注解
用于指定一个自定义的反序列化器,将 JSON 字符串转换为 Java 对象。
通过在属性、setter 方法或类级别上使用 @JsonDeserialize 注解,可以指定要使用的反序列化器。
这使得你可以控制如何将 JSON 字符串转换为对象,包括处理特殊格式、类型转换等。
import com.fasterxml.jackson.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
public class Person {
private String name;
private int age;
// 省略构造函数和getter/setter方法
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Person person = new Person("John", 30);
String json = mapper.writeValueAsString(person);
System.out.println(json); // 输出:{"fullName":"John","years":30}
Person deserializedPerson = mapper.readValue(json, Person.class);
System.out.println(deserializedPerson); // 输出:Person{name='John', age=30}
}
}
class CustomSerializer extends JsonSerializer<Person> {
@Override
public void serialize(Person person, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("fullName", person.getName());
jsonGenerator.writeNumberField("years", person.getAge());
jsonGenerator.writeEndObject();
}
}
class CustomDeserializer extends JsonDeserializer<Person> {
@Override
public Person deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String fullName = node.get("fullName").asText();
int years = node.get("years").asInt();
return new Person(fullName, years);
}
}
在上面的示例中,我们使用了 @JsonSerialize(using = CustomSerializer.class) 注解来指定自定义的序列化器 CustomSerializer,它将 Person 对象转换为包含 “fullName” 和 “years” 字段的 JSON 字符串。同时,我们使用了 @JsonDeserialize(using = CustomDeserializer.class) 注解来指定自定义的反序列化器 CustomDeserializer,它将 JSON 字符串中的 “fullName” 和 “years” 字段解析为 Person 对象。
通过使用 @JsonSerialize 和 @JsonDeserialize 注解,你可以灵活地控制序列化和反序列化过程中的操作,包括自定义字段命名、格式转换等。
2 @JsonProperty
作用:指定在 JSON 序列化和反序列化过程中使用的属性名称。
public class MyClass {
@JsonProperty("customName")
private String property;
// Getter and Setter methods
}
3 @JsonIgnore
作用:指示 Jackson 序列化和反序列化过程中忽略被注解的属性。
public class MyClass {
@JsonIgnore
private String property;
// Getter and Setter methods
}
4 @JsonFormat
用于指定在将 Java 对象序列化为 JSON 字符串或从 JSON 字符串反序列化为 Java 对象时,对日期、时间等特殊类型的字段进行格式化的方式。它的作用是控制日期、时间等特殊类型字段的序列化和反序列化格式。
下面是 @JsonFormat 注解的一些常见用法:
4.1 格式化日期
你可以使用 @JsonFormat 注解来指定日期字段在序列化为 JSON 字符串时的格式,以及在从 JSON 字符串反序列化为 Java 对象时的格式。
import com.fasterxml.jackson.annotation.JsonFormat;
public class Event {
@JsonFormat(pattern = "yyyy-MM-dd")
private Date eventDate;
// 省略构造函数和getter/setter方法
}
在上面的例子中,我们指定了 eventDate 字段在序列化和反序列化时采用 “yyyy-MM-dd” 的日期格式。
4.2 格式化时间
除了日期,你也可以使用 @JsonFormat 注解来指定时间字段的格式化方式。
import com.fasterxml.jackson.annotation.JsonFormat;
public class Meeting {
@JsonFormat(pattern = "HH:mm:ss")
private LocalTime startTime;
// 省略构造函数和getter/setter方法
}
在这个例子中,我们指定了 startTime 字段在序列化和反序列化时采用 “HH:mm:ss” 的时间格式。
4.3 其他格式化选项
除了 pattern 属性,@JsonFormat 注解还支持其他属性,如 timezone、shape 等,用于更精细地控制字段的序列化和反序列化行为。
import com.fasterxml.jackson.annotation.JsonFormat;
public class Payment {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "GMT+8")
private LocalDateTime paymentTime;
// 省略构造函数和getter/setter方法
}
在上述示例中,我们使用了 @JsonFormat 注解来指定 paymentTime 字段的格式为 ISO8601 格式,并且时区为 GMT+8。
通过使用 @JsonFormat 注解,你可以灵活地控制日期、时间等特殊类型字段的序列化和反序列化格式,确保 JSON 数据与 Java 对象之间能够正确地进行转换。
5 @JsonUnwrapped
当使用 @JsonUnwrapped 注解时,它会在序列化和反序列化过程中起到以下作用:
5.1 序列化(Serialization)
在序列化过程中,@JsonUnwrapped 注解告诉 Jackson 库将嵌套对象的属性合并到外层对象中,从而在生成的 JSON 数据中直接包含嵌套对象的属性。这样可以减少生成的 JSON 结构中的层级,使其更加扁平化。
5.2 反序列化(Deserialization)
在反序列化过程中,@JsonUnwrapped 注解告诉 Jackson 库将指定的属性值从 JSON 数据中提取出来,并填充到外层对象的对应属性中。这样可以让 JSON 数据中的扁平结构直接映射到外层对象的属性上,简化了处理嵌套结构的代码逻辑。
下面是 @JsonUnwrapped 注解的使用方法示例:
考虑一个名为 Employee 的 Java 类,包含嵌套的 Address 对象:
import com.fasterxml.jackson.annotation.JsonUnwrapped;
public class Employee {
private String name;
@JsonUnwrapped
private Address address;
// 省略构造函数和getter/setter方法
}
public class Address {
private String city;
private String street;
// 省略构造函数和getter/setter方法
}
如果有一个名为 employee 的 Employee 对象:
Employee employee = new Employee("John Doe", new Address("New York", "123 Main St"));
在序列化时,employee 对象将被转换为如下的 JSON 结构:
{
"name": "John Doe",
"city": "New York",
"street": "123 Main St"
}
在反序列化时,以下 JSON 数据:
{
"name": "Jane Smith",
"city": "San Francisco",
"street": "456 Elm St"
}
将会被转换为一个包含相应属性的 Employee 对象。
除了基本用法,@JsonUnwrapped 注解还支持一些属性,如 prefix 和 suffix,用于控制展开的属性在合并到外层对象时是否添加前缀或后缀。
import com.fasterxml.jackson.annotation.JsonUnwrapped;
public class Contact {
@JsonUnwrapped(prefix = "home_")
private Address homeAddress;
@JsonUnwrapped(prefix = "work_")
private Address workAddress;
// 省略构造函数和getter/setter方法
}
在这个例子中,我们使用了 @JsonUnwrapped 注解的 prefix 属性,将 homeAddress 和 workAddress 对象的属性展开到 Contact 对象中时,会在属性名前添加前缀,分别为 “home_” 和 “work_”。
通过这个示例,你可以看到使用 @JsonUnwrapped 注解后,嵌套对象的属性被直接合并到外层对象中,使得 JSON 数据与 Java 对象之间的转换更加简洁和直观。
6 @JsonAnyGetter
作用:用于将对象的属性按键值对的形式输出为 Map,包括动态属性。将动态属性以键值对的形式合并到 JSON 中
示例代码:
public class MyClass {
private Map<String, Object> properties = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> getProperties() {
return properties;
}
public void addProperty(String key, Object value) {
properties.put(key, value);
}
}
在上述示例中,使用 @JsonAnyGetter 注解标记了 getProperties 方法,将对象的动态属性以键值对的形式输出为 Map。通过 addProperty 方法可以动态地添加属性到 properties Map 中。
7 @JsonInclude
用于控制在序列化过程中如何处理属性值为 null 的情况。它的作用是指定在将对象转换为 JSON 字符串时是否包含属性值为 null 的字段。
@JsonInclude 注解可以应用在类级别或属性级别上。
7.1 类级别的 @JsonInclude 注解
当应用在类级别上时,@JsonInclude 注解指示了默认的 null 处理策略,该策略会应用到整个类的所有属性上。
通过设置 @JsonInclude 的 value 属性,可以指定序列化过程中的 null 处理策略,常用的取值包括:
Include.ALWAYS:始终包含属性值为 null 的字段。
Include.NON_NULL:仅包含属性值不为 null 的字段。
Include.NON_EMPTY:仅包含属性值不为 null 且不为空(如空字符串、空集合)的字段。
Include.USE_DEFAULTS:使用默认的 null 处理策略。
7.2 属性级别的 @JsonInclude 注解
当应用在属性级别上时,@JsonInclude 注解可以覆盖类级别的默认 null 处理策略,为该属性指定独立的 null 处理策略。
通过设置 @JsonInclude 的 value 属性,可以指定序列化过程中该属性的 null 处理策略,取值与类级别的注解相同。
以下是一个示例,演示了如何使用 @JsonInclude 注解:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
private String name;
private Integer age;
private String address;
// 省略构造函数和getter/setter方法
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Person person = new Person("John", null, null);
String json = mapper.writeValueAsString(person);
System.out.println(json); // 输出:{"name":"John"}
Person deserializedPerson = mapper.readValue(json, Person.class);
System.out.println(deserializedPerson); // 输出:Person{name='John', age=null, address=null}
}
}
在上面的示例中,@JsonInclude(JsonInclude.Include.NON_NULL) 注解被应用在类级别上,表示在序列化过程中仅包含属性值不为 null 的字段。因此,只有 name 字段被包含在最终生成的 JSON 中,而 age 和 address 字段由于值为 null 而被忽略。
8 @JsonAlias
作用:指定属性的别名,在反序列化时将别名与属性进行映射。
示例代码:
public class MyClass {
@JsonAlias({"name", "fullName"})
private String property;
// Getter and Setter methods
}
上述代码中,使用 @JsonAlias 注解指定了 name 和 fullName 这两个别名,当 JSON 数据中包含这两个键时,它们都会与 property 属性进行映射。
9 @JsonIgnoreProperties
作用:指定在序列化和反序列化过程中需要忽略的属性。
示例代码:
@JsonIgnoreProperties({"property1", "property2"})
public class MyClass {
private String property1;
private String property2;
private String property3;
// Getter and Setter methods
}
上述代码中,使用 @JsonIgnoreProperties 注解指定了忽略 property1 和 property2 这两个属性,它们在序列化和反序列化过程中将被忽略。
10 @JsonManagedReference 和 @JsonBackReference
作用:用于解决循环引用的问题,即某个对象与其他对象存在相互引用的情况。
示例代码:
public class Parent {
private String name;
@JsonManagedReference
private List<Child> children;
// Getter and Setter methods
}
public class Child {
private String name;
@JsonBackReference
private Parent parent;
// Getter and Setter methods
}
上述代码中,@JsonManagedReference 注解用于标注父对象中的子对象集合,而 @JsonBackReference 注解用于标注子对象中的父对象引用。这样可以防止循环引用导致的无限递归问题。
11 @JsonCreator
作用:在反序列化过程中,用于指定一个静态工厂方法或构造函数,用于创建对象实例。
示例代码:
public class MyClass {
private String property;
@JsonCreator
public MyClass(@JsonProperty("property") String property) {
this.property = property;
}
// Getter method for property
}
上述代码中,使用 @JsonCreator 注解标注了一个构造函数,并通过 @JsonProperty 指定了属性与 JSON 中的字段进行映射。
12 @JsonTypeInfo
作用:在序列化和反序列化过程中,用于处理多态类型。
示例代码:
@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 abstract class Animal {
// Common properties and methods
}
public class Dog extends Animal {
// Dog-specific properties and methods
}
public class Cat extends Animal {
// Cat-specific properties and methods
}
上述代码中,使用 @JsonTypeInfo 注解指定了类型信息在序列化和反序列化中的处理方式,并使用 @JsonSubTypes 注解标注了派生类与其对应的类型标识。
13 @JsonFilter
用于动态过滤在序列化过程中要包含的属性。它允许你在运行时动态地指定要序列化的属性,这在某些场景下非常有用,比如根据用户权限或者其他条件决定序列化的内容。
13.1 使用 @JsonFilter 注解定义过滤器
首先,你需要定义一个过滤器,通过给过滤器指定名称,并将其应用到需要动态过滤的类上。
import com.fasterxml.jackson.annotation.JsonFilter;
@JsonFilter("myFilter")
public class MyDto {
private String name;
private int age;
private String email;
// 省略构造函数和getter/setter方法
}
在上述示例中,我们使用 @JsonFilter 注解为 MyDto 类定义了一个名为 “myFilter” 的过滤器。
13.2 配置 ObjectMapper 使用过滤器
接下来,你需要配置 ObjectMapper 来使用这个过滤器。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name", "age"));
mapper.setFilterProvider(filterProvider);
在这个示例中,我们创建了一个 SimpleFilterProvider,并使用 addFilter 方法将过滤器应用到 ObjectMapper 中。在这个特定的过滤器中,我们只包含了 “name” 和 “age” 两个属性。
13.3 应用过滤器进行序列化
最后,在进行序列化时,你可以指定要使用的过滤器。
String json = mapper.writer(filterProvider).writeValueAsString(myDto);
在这个示例中,我们使用配置了过滤器的 ObjectMapper 对象来将 myDto 对象序列化为 JSON 字符串。在序列化过程中,只会包含 “name” 和 “age” 两个属性,因为我们在过滤器中指定了这两个属性。
通过使用 @JsonFilter 注解,你可以实现动态过滤要序列化的属性,根据需求灵活地控制序列化结果,这对于构建灵活的 RESTful API 或者处理动态权限控制都非常有用。
14 @JsonAnySetter
作用:允许将未匹配到具体字段的键值对动态地注入到 Java 对象中。
示例代码:
public class MyClass {
private Map<String, Object> additionalProperties = new HashMap<>();
@JsonAnySetter
public void setAdditionalProperty(String key, Object value) {
additionalProperties.put(key, value);
}
}
在上述示例中,使用 @JsonAnySetter 注解标记了 setAdditionalProperty 方法,当反序列化 JSON 对象时,其中的未匹配到的键值对会被注入到 additionalProperties 字段中。
15 @JsonAppend
作用:允许用户在序列化时动态地添加属性到 JSON 对象中,这些属性可能源自于 Java 对象的不同字段或方法。
示例代码:
@Getter
@Setter
@AllArgsConstructor(staticName = "of")
@NoArgsConstructor
@JsonAppend(attrs = {@JsonAppend.Attr(value = "age"),@JsonAppend.Attr(value = "height")},
props = {@JsonAppend.Prop(value =TestWriter.class ,type = String.class,name = "version")})
class JsonPropertyPojo{
private String sex;
private String name;
private String unknown;
}
@NoArgsConstructor
class TestWriter extends VirtualBeanPropertyWriter{
private TestWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) {
super(propDef, contextAnnotations, declaredType);
}
@Override
protected Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
Field nameField = ReflectionUtils.findField(bean.getClass(),"name");
ReflectionUtils.makeAccessible(nameField);
if( nameField.get(bean).toString().length()>2){
return "1.2";
}
return "1.0";
}
@Override
public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) {
return new TestWriter(propDef, declaringClass.getAnnotations(), type);
}
}
# 测试代码如下
@Test
public void JsonAppendTest() throws Exception{
CombineJacksonAnnotation.JsonPropertyPojo pojo = CombineJacksonAnnotation.JsonPropertyPojo.of("男","小小刘","some");
System.out.println(om.writerFor(CombineJacksonAnnotation.JsonPropertyPojo.class).withAttribute("age","10").withAttribute("height","12").writeValueAsString(pojo));
}
# 序列化结果如下
{
"sex" : "男",
"name" : "小小刘",
"unknown" : "some",
"age" : "10",
"height" : "12",
"version" : "1.2"
}
通过上面的例子可以看到,@JsonAppend提供了两种方式来动态的添加虚拟字段
- 1 attrs
此种方式需要在序列化时候手动的添加Attribute,如下
om.writerFor(CombineJacksonAnnotation.JsonPropertyPojo.class).withAttribute(“age”,“10”).withAttribute(“height”,“12”) - 2 props
此种方式比较灵活,但是要实现一个VirtualBeanPropertyWriter类即可,如果真的有这种需求,推荐使用第二种方式来实现
16 @JsonIgnoreType
作用: 指示 Jackson 在序列化和反序列化过程中忽略被注解的类型。这意味着被 @JsonIgnoreType 注解的类型将会被完全忽略,不会被包含在最终生成的 JSON 中,也不会被用于反序列化。
通常情况下,@JsonIgnoreType 注解会被用于一些辅助性的、不需要被序列化和反序列化的类型,或者是一些与 JSON 交互无关的类型。通过使用 @JsonIgnoreType 注解,你可以告诉 Jackson 忽略这些类型,从而避免在 JSON 序列化和反序列化过程中处理它们。
import com.fasterxml.jackson.annotation.JsonIgnoreType;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
MyEntity entity = new MyEntity("John", new AdditionalInfo("some info"));
String json = mapper.writeValueAsString(entity);
System.out.println(json); // 输出:{"name":"John"}
MyEntity deserializedEntity = mapper.readValue(json, MyEntity.class);
System.out.println(deserializedEntity); // 输出:MyEntity{name='John', additionalInfo=null}
}
}
@JsonIgnoreType
class AdditionalInfo {
private String info;
// 省略构造函数和getter/setter方法
}
class MyEntity {
private String name;
private AdditionalInfo additionalInfo;
// 省略构造函数和getter/setter方法
}
在上面的示例中,AdditionalInfo 类被标记为 @JsonIgnoreType,因此在序列化和反序列化过程中会被忽略。当对 MyEntity 对象进行序列化时,只有 name 字段会被包含在最终的 JSON 中,而 additionalInfo 字段则会被忽略。在反序列化时,即使 JSON 中包含了 additionalInfo 字段,它也不会被用于构建 MyEntity 对象。
17 @JsonGetter 和 @JsonSetter
作用: 用于指定在序列化和反序列化过程中 JSON 属性的命名规则以及自定义属性的读取和写入方法。它们的作用如下:
17.1 @JsonGetter 注解
- 1) 用于指定一个非标准的 getter 方法作为 JSON 属性的读取方法。
- 2) 通过在非标准的 getter 方法上使用 @JsonGetter 注解,可以指定该方法对应的 JSON 属性的名称。
- 3) 这使得你可以将 Java 对象中的属性映射到不同于属性名的 JSON 属性,从而实现更灵活的属性命名。
17.2 @JsonSetter 注解
- 1)用于指定一个非标准的 setter 方法作为 JSON 属性的写入方法。
- 2)通过在非标准的 setter 方法上使用 @JsonSetter 注解,可以指定该方法对应的 JSON 属性的名称。
- 3) 这使得你可以将 JSON 中的属性值映射到不同于属性名的 Java 对象属性,从而实现更灵活的属性赋值。
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "{\"first_name\":\"John\",\"last_name\":\"Doe\"}";
Person person = mapper.readValue(json, Person.class);
System.out.println(person.getFullName()); // 输出:John Doe
String outputJson = mapper.writeValueAsString(person);
System.out.println(outputJson); // 输出:{"first_name":"John","last_name":"Doe"}
}
}
class Person {
private String firstName;
private String lastName;
@JsonGetter("full_name")
public String getFullName() {
return firstName + " " + lastName;
}
@JsonSetter("first_name")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@JsonSetter("last_name")
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
在上面的示例中,Person 类中的 getFullName 方法使用了 @JsonGetter(“full_name”) 注解,以指定返回的全名属性对应的 JSON 属性名称为 “full_name”。同时,setFirstName 和 setLastName 方法使用了 @JsonSetter 注解,以指定它们对应的 JSON 属性名称。
通过使用 @JsonGetter 和 @JsonSetter 注解,你可以在 Jackson 序列化和反序列化过程中灵活地控制 JSON 属性的命名规则和自定义属性的读取和写入方法。
18 @JsonPropertyOrder
作用: 在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonPropertyOrder 可以指定属性在 json 字符串中的顺序
2️⃣Jackson 库中的模块
下面介绍一些 Jackson 库中比较常用的模块:
2.1 databind
作用:提供了 JSON 序列化和反序列化的核心功能,可以将 Java 对象和 JSON 数据相互转换。
示例代码:
ObjectMapper objectMapper = new ObjectMapper();
MyClass myObject = objectMapper.readValue(json, MyClass.class);
String json = objectMapper.writeValueAsString(myObject);
2.2 annotations
作用:提供了一系列注解,用于控制序列化和反序列化过程中的行为和选项。
示例代码:
public class MyClass {
@JsonProperty("my_property")
private String property;
// Getter and Setter methods
}
2.3 coreutils
作用:提供一些基础工具类和函数,用于支持序列化和反序列化过程中所需的类型转换和其他操作。
示例代码:
// Convert JSON string to JsonNode object
JsonNode jsonNode = objectMapper.readTree(jsonString);
// Convert object to Map
Map<String, Object> map = objectMapper.convertValue(myObject, new TypeReference<Map<String, Object>>() {});
// Convert object to byte array
byte[] bytes = objectMapper.writeValueAsBytes(myObject);
2.4 datatype-jsr310
作用:提供对 Java 8 时间类的支持,包括 LocalDateTime、ZonedDateTime、Instant 等。
示例代码:
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
上述代码中,使用 JavaTimeModule 注册模块,启用对 Java 8 时间类的支持。
2.5 jaxrs-json-provider
作用:提供了 JAX-RS 规范中 JSON 消息转换器的实现,适用于 Web 应用程序中返回 JSON 数据的场景。
示例代码:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMyObject() {
MyClass myObject = myService.getMyObject();
return Response.ok(myObject).build();
}
// Register JSON provider
register(JacksonJaxbJsonProvider.class);
这些模块提供了丰富的功能和选项,以满足不同场景下的需求。请根据具体情况选择适当的模块来使用
3️⃣ Jackson 库的扩展点
Jackson 库提供了一些扩展点,使得用户可以扩展序列化和反序列化过程中的行为和选项。下面是一些常用的扩展点:
3.1 JsonSerializer 和 JsonDeserializer
作用:用于自定义 Java 对象和 JSON 数据的转换过程。
代码:
public class MyClassSerializer extends JsonSerializer<MyClass> {
@Override
public void serialize(MyClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("my_property", value.getProperty());
gen.writeEndObject();
}
}
public class MyClassDeserializer extends JsonDeserializer<MyClass> {
@Override
public MyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode jsonNode = p.getCodec().readTree(p);
return new MyClass(jsonNode.get("my_property").asText());
}
}
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(MyClass.class, new MyClassSerializer());
module.addDeserializer(MyClass.class, new MyClassDeserializer());
objectMapper.registerModule(module);
3.2 StdConverter
作用:用于提供类型转换的实现,可以用于自定义注解的处理等场景。
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Masked {
boolean value() default true;
}
public class MaskedStringConverter extends StdConverter<String, String> {
@Override
public String convert(String value) {
if (value == null) {
return null;
}
if (value.length() > 4) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
if (i < value.length() - 4) {
builder.append('*');
} else {
builder.append(value.charAt(i));
}
}
return builder.toString();
} else {
return value;
}
}
}
public class MaskedStringModifier extends BeanPropertyModifierBase {
@Override
public BeanPropertyDefinition updateBuilder(SerializationConfig config,
BeanDescription beanDesc,
BeanPropertyDefinition propDef) {
AnnotatedField field = propDef.getField();
if (field == null) {
return propDef;
}
Masked masked = field.getAnnotation(Masked.class);
if (masked == null || !masked.value()) {
return propDef;
}
return propDef.withSerializer(new StdDelegatingSerializer(new MaskedStringConverter()));
}
}
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MaskedStringModifier());
objectMapper.registerModule(module);
3.3 JsonNodeFactory
作用:用于提供自定义的 JsonNode 对象的生成策略。
代码:
JsonNodeFactory customNodeFactory = new JsonNodeFactory() {
@Override
public ObjectNode objectNode() {
return new CustomObjectNode(this);
}
};
class CustomObjectNode extends ObjectNode {
public CustomObjectNode(JsonNodeFactory nc) {
super(nc);
}
public CustomObjectNode(JsonNodeFactory nc, Map<String, JsonNode> m) {
super(nc, m);
}
@Override
public String toString() {
return "CustomObjectNode[" + super.toString() + "]";
}
}
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setNodeFactory(customNodeFactory);
3.4 JsonDeserializerModifier 和 JsonSerializerModifier
作用:允许对默认的 JsonDeserializer 和 JsonSerializer 进行修改或替换。
代码:
public class MyJsonSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config,
BeanDescription beanDesc,
JsonSerializer<?> serializer) {
if (beanDesc.getBeanClass() == MyClass.class) {
return new MyJsonSerializer();
}
return super.modifySerializer(config, beanDesc, serializer);
}
}
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MyJsonSerializerModifier());
objectMapper.registerModule(module);
3.5 ValueInstantiator
作用:用于自定义对象实例化的逻辑,例如使用工厂方法或者构造器参数注入等。
代码:
public class MyClassValueInstantiator extends ValueInstantiator.Base {
@Override
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
// 可以在此处添加自定义的实例化逻辑
return new MyClass();
}
}
SimpleModule module = new SimpleModule();
module.addValueInstantiator(MyClass.class, new MyClassValueInstantiator());
objectMapper.registerModule(module);
3.6 ObjectIdResolver
作用:用于自定义对象与唯一标识符之间的映射关系,用于处理循环引用等场景。
代码:
public class MyObjectIdResolver implements ObjectIdResolver {
// 实现方法...
}
DefaultSerializerProvider.Impl sp = new DefaultSerializerProvider.Impl();
sp.setObjectIdResolver(new MyObjectIdResolver());
objectMapper.setSerializerProvider(sp);
3.7 ObjectIdentityGenerator
作用:用于生成对象唯一标识符(Object Id)。
代码:
public class MyObjectIdentityGenerator extends ObjectIdentityGenerator<MyObject> {
// 实现方法...
}
SimpleModule module = new SimpleModule();
module.setIdentityInfoGenerator(new MyObjectIdentityGenerator());
objectMapper.registerModule(module);
这些扩展点提供了更高级别的定制化能力,允许用户根据具体需求对序列化和反序列化过程进行更细粒度的控制