在 Spring Boot 1.2.3.RELEASE 中使用 fastxml 将
LocalDate
字段序列化和反序列化为 ISO 日期格式字符串的正确方法是什么?
我已经尝试过:
spring.jackson.serialization.write-dates-as-timestamps:false
在application.properties文件中,
在项目中包含jackson-datatype-jsr310然后使用
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
注释
和
@DateTimeFormat(iso=ISO.DATE)
注释,
添加
Jsr310DateTimeFormatAnnotationFormatterFactory
作为格式化程序:
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new Jsr310DateTimeFormatAnnotationFormatterFactory());
}
以上都没有帮助。
compile ("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
在 build.gradle 中 然后以下注释有所帮助:
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthday;
更新:如果您使用的是 Spring Boot 2.*,则依赖项已通过“启动器”之一包含在内。
在我的 Spring Boot 2 应用程序中
@JsonFormat
注释用于 REST 控制器中(反)序列化 JSON 数据时。@DateTimeFormat
注释用于其他控制器ModelAttribute
当(反)序列化字符串数据时。您可以在同一字段上指定两者(如果您在 JSON 和 Thymeleaf 模板之间共享 DTO,则很有用):
@JsonFormat(pattern = "dd/MM/yyyy")
@DateTimeFormat(pattern = "dd/MM/yyyy")
private LocalDate birthdate;
Gradle 依赖:
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-json'
我希望这就是您在 Spring Boot 2.x 应用程序中自定义日期/时间格式所需的所有配置。
对于 Spring Boot 1.x 应用程序,指定其他注释和依赖项:
@JsonFormat(pattern = "dd/MM/yyyy")
@DateTimeFormat(pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthDate;
// or
@JsonFormat(pattern = "dd/MM/yyyy HH:mm")
@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime birthDateTime;
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.9.8'
请注意,如果有人以错误的格式发送日期,您的 API 将抛出“JSON 解析错误”。映射示例:
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate releaseDate;
异常示例:
:JSON 解析错误:无法从字符串“2002”反序列化HttpMessageNotReadableException
类型的值:无法反序列化java.time.LocalDate
:(java.time.LocalDate
) 无法在索引 4 处解析文本“2002”;嵌套异常是java.time.format.DateTimeParseException
:无法从字符串“2002”反序列化com.fasterxml.jackson.databind.exc.InvalidFormatException
类型的值:无法反序列化java.time.LocalDate
:(java.time.LocalDate
)无法在索引4处解析文本“2002”java.time.format.DateTimeParseException
如果您想使用自定义 Java 日期格式化程序,请添加
@JsonFormat
注释。
@JsonFormat(pattern = "dd/MM/yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate birthdate;*
实际上,只要在 pom.xml 中指定依赖就可以了。
这样,我所有的 LocalDate 字段都会自动使用 ISO 格式,无需注释它们:
<!-- This is enough for LocalDate to be deserialized using ISO format -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
在 Spring Boot 1.5.7 上测试。
您可能有兴趣在全局注册它,而不是为所有 LocalDate 属性指定序列化器/反序列化器。您需要重写 Spring 用于序列化/反序列化的默认 ObjectMapper 的配置。这是一个例子:
@Configuration
public class ObjectMapperConfiguration {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// Registro global do serializer/deserializer para datas sem horário
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer());
simpleModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
mapper.registerModule(simpleModule);
return mapper;
}
}
这样,Jackson 将始终对定义的数据类型使用指定的序列化器/反序列化器,而无需注释类属性。
信息:您必须将 jackson-databind 依赖项添加到 pom.xml 才能拥有自定义序列化器/反序列化器代码功能:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
builder.serializerByType(LocalDate.class, new LocalDateSerializer(localDateFormatter));
builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(localDateFormatter));
DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(localDateTimeFormatter));
};
}
您可能会在不同的课程中使用
LocalDateTime
或 LocalDate
。创建一个配置类并添加自定义 ObjectMapper
bean 可以提供帮助:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomMapper {
@Bean
public ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
//The below helped me to solve the issue
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return objectMapper;
}