下面是详细讲解“Jackson反序列化@JsonFormat 不生效的解决方案”的完整攻略。
问题背景
在Java开发中,我们常常需要将JSON字符串或者文件反序列化成Java的对象。使用Jackson库是常见的做法,而@JsonFormat注解可以给Java对象的某个属性设置序列化/反序列化的格式。但是有时候我们会发现@JsonFormat注解不生效,即使已经正确地在Java类中设置了该注解,反序列化时仍然不能按照我们期望的格式进行。
解决方案
经过调查,发现在使用Jackson反序列化@JsonFormat时,需要使用ObjectMapper对象来进行反序列化操作,并设置一个JavaTimeModule模块来支持Java 8中的新日期时间类,否则@JsonFormat注解可能不会生效。
下面是具体的代码解析。
首先,我们需要在Java类的日期类型属性上添加@JsonFormat注解。例如:
import com.fasterxml.jackson.annotation.JsonFormat;
public class User {
private Integer id;
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
// Getters and Setters
}
然后,在反序列化时需要调用ObjectMapper的configure()方法,传入一个JavaTimeModule模块。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class Main {
public static void main(String[] args) throws Exception {
String json = "{\"id\": 1, \"name\": \"Bob\", \"createTime\": \"2022-12-02 12:34:56\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
User user = objectMapper.readValue(json, User.class);
System.out.println(user.getCreateTime());
}
}
在这个例子中,我们使用了一个JSON字符串,通过ObjectMapper的readValue()方法将其反序列化成User对象。需要注意的是,在ObjectMapper的构造函数中,我们调用了registerModule()方法,并将一个JavaTimeModule实例传递进去。这个模块将会支持Java 8新的日期时间处理类。
于是,我们就能够成功反序列化User对象并得到正确的日期时间属性了。
示例
下面提供两个具体的示例,以便更好地理解问题和解决方案。
示例1
在这个示例中,我们定义了一个Student类,其中包含了一个LocalDateTime类型的属性updateTime。我们在属性上添加了@JsonFormat注解,并指定了日期时间的格式为"yyyy-MM-dd HH:mm:ss"。
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
public class Student {
private Integer id;
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}
接着,我们使用ObjectMapper进行反序列化,在main()方法中定义了一个JSON字符串,并使用ObjectMapper的readValue()方法将其反序列化成Student对象。需要注意的是,在ObjectMapper的构造函数中,我们调用了registerModule()方法,并将一个JavaTimeModule实例传递进去。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"id\": 1, \"name\": \"Alice\", \"updateTime\": \"2022-12-02 12:34:56\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
Student student = objectMapper.readValue(json, Student.class);
System.out.println(student.getUpdateTime());
}
}
输出结果为:
2022-12-02T12:34:56
这说明我们成功地反序列化了Student对象,并且日期时间格式符合我们的期望。
示例2
在这个示例中,我们定义了一个Person类,其中包含了一个Date类型的属性birthday。我们在属性上添加了@JsonFormat注解,并指定了日期时间的格式为"yyyy-MM-dd"。
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class Person {
private Integer id;
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
接着,我们使用ObjectMapper进行反序列化,在main()方法中定义了一个JSON字符串,并使用ObjectMapper的readValue()方法将其反序列化成Person对象。同样地,在ObjectMapper的构造函数中,我们调用了registerModule()方法,并将一个JavaTimeModule实例传递进去。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"id\": 1, \"name\": \"Jack\", \"birthday\": \"1990-05-12\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
Person person = objectMapper.readValue(json, Person.class);
System.out.println(person.getBirthday());
}
}
输出结果为:
Fri May 11 20:00:00 PDT 1990
从结果可以看出,我们成功地反序列化了Person对象,但是出现了一个问题:从JSON字符串中反序列化得到的Date对象的时间不正确。这是因为Java 8中的日期时间类和旧版本的日期时间类在序列化/反序列化时,存在不兼容的问题。
解决方案是使用Java 8中的日期时间类。我们只需要更改Person类中的Birthday属性为LocalDate类型,在ObjectMapper的readValue()方法中指定LocalDate类型即可。代码如下:
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDate;
public class Person {
private Integer id;
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getBirthday() {
return birthday;
}
public void setBirthday(LocalDate birthday) {
this.birthday = birthday;
}
}
接着,我们使用ObjectMapper进行反序列化,在main()方法中定义了一个JSON字符串,并使用ObjectMapper的readValue()方法将其反序列化成Person对象。同样地,在ObjectMapper的构造函数中,我们调用了registerModule()方法,并将一个JavaTimeModule实例传递进去。需要注意的是,在readValue()方法中,我们使用了LocalDate.class来指定birthday属性的类型。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.time.LocalDate;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"id\": 1, \"name\": \"Jack\", \"birthday\": \"1990-05-12\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
Person person = objectMapper.readValue(json, Person.class);
System.out.println(person.getBirthday());
}
}
输出结果为:
1990-05-12
从结果可以看出,我们成功地反序列化了Person对象,并且日期格式也符合了我们的期望。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Jackson反序列化@JsonFormat 不生效的解决方案 - Python技术站