@JsonProperty
是 Jackson 库中的注解,用于指定 JSON 数据与 Java 对象之间的映射。它可以用在构造方法参数 或类属性上,但两者的行为和使用场景有所不同。
1. @JsonProperty
用在构造方法参数上
当 @JsonProperty
用在构造方法参数上时,Jackson 会使用该构造方法来反序列化 JSON 数据到 Java 对象。它会根据 JSON 数据中的字段名称匹配构造方法参数上的 @JsonProperty
注解。
特点:
- 构造方法驱动的反序列化 :Jackson 会根据 JSON 数据调用带有
@JsonProperty
注解的构造方法来创建对象。 - 不可变对象支持 :适用于不可变对象(
final
属性)的场景,因为属性只能通过构造方法赋值。 - 更安全的初始化:所有属性在对象创建时就被初始化,避免了后续的 setter 方法调用。
示例:
java
public class UserInfo {
private final String userType;
private final PhoneNumber phoneNumber;
public UserInfo(@JsonProperty("userType") final String userType,
@JsonProperty("phoneNumber") final PhoneNumber phoneNumber) {
this.userType = userType;
this.phoneNumber = phoneNumber;
}
}
JSON 数据:
java
{
"userType": "admin",
"phoneNumber": {
"countryCode": "+1",
"number": "1234567890"
}
}
反序列化过程:
- Jackson 会解析 JSON 数据,并根据
@JsonProperty
注解找到对应的构造方法参数。 - 调用构造方法
UserInfo(String userType, PhoneNumber phoneNumber, String nuId)
创建对象。
2. @JsonProperty
用在属性上
当 @JsonProperty
用在类属性上时,Jackson 会通过默认的无参构造方法创建对象,然后通过反射调用属性的 setter 方法(或直接访问字段)来设置值。
特点:
- 基于默认构造方法的反序列化:需要类有一个无参构造方法(如果没有显式定义,Java 会提供一个默认的无参构造方法)。
- 支持可变对象:适用于需要通过 setter 方法或直接修改属性值的场景。
- 更灵活的映射:可以直接在属性上定义 JSON 字段名称,避免在构造方法中显式声明。
示例:
java
public class UserInfo {
@JsonProperty("userType")
private String userType;
@JsonProperty("phoneNumber")
private PhoneNumber phoneNumber;
// 无参构造方法
public UserInfo() {}
// Getters and Setters
}
JSON 数据:
java
{
"userType": "admin",
"phoneNumber": {
"countryCode": "+1",
"number": "1234567890"
}
}
反序列化过程:
- Jackson 会调用无参构造方法创建
UserInfo
对象。 - 根据
@JsonProperty
注解找到对应的 JSON 字段,并通过反射设置属性值。
3. 两者的主要区别
特性 | 用在构造方法参数上 | 用在属性上 |
---|---|---|
对象创建方式 | 使用带注解的构造方法创建对象 | 使用无参构造方法创建对象 |
适用场景 | 不可变对象(final 属性) |
可变对象 |
依赖的构造方法 | 必须有带 @JsonProperty 注解的构造方法 |
必须有无参构造方法 |
灵活性 | 需要在构造方法中定义所有需要的属性 | 可以在类中定义部分或全部属性 |
性能 | 构造方法反序列化性能稍高(少一次反射调用) | 通过反射设置属性,性能稍低 |
代码风格 | 更适合不可变对象和构造方法初始化的场景 | 更适合传统的 Java Bean 风格 |
4. 如何选择
-
使用构造方法参数上的
@JsonProperty
:- 如果类是不可变的(
final
属性)。 - 如果希望在对象创建时就完成所有属性的初始化。
- 如果类没有无参构造方法,或者不希望提供无参构造方法。
- 如果类是不可变的(
-
使用属性上的
@JsonProperty
:- 如果类是可变的(需要 setter 方法或直接修改属性)。
- 如果需要更灵活的 JSON 映射。
- 如果类需要与传统的 Java Bean 风格兼容。
5. 总结
- 构造方法上的
@JsonProperty
更适合不可变对象,确保对象在创建时就被完全初始化。 - 属性上的
@JsonProperty
更适合可变对象,提供更灵活的映射方式。