简体   繁体   English

Spring引导2.04 Jackson无法将LocalDateTime序列化为String

[英]Spring boot 2.04 Jackson cannot serialize LocalDateTime to String

I have Spring boot application and LocalDateTime properties serialized as JSON array, instead of String. 我将Spring启动应用程序和LocalDateTime属性序列化为JSON数组,而不是String。

As I found while search on web, all I need is to set up in application.properties 正如我在网上搜索时发现的,我只需要在application.properties中进行设置

spring.jackson.serialization.write-dates-as-timestamps=false

I also tried to put jackson-datatype-jsr310 to dependencies, but no luck either 我也尝试将jackson-datatype-jsr310放到依赖项中,但也没有运气

Also I tried to add annotation: 我也尝试添加注释:

@DateTimeFormat(iso = ISO.DATE_TIME)

it not helps too. 它也没有帮助。

I saw a lot of people get in something similar, but their solutions seems related to Spring Boot 1.x, while I use 2.04 我看到很多人都有类似的东西,但他们的解决方案似乎与Spring Boot 1.x有关,而我使用的是2.04

Also I use Lombok, but not sure is it affects serialization format. 我也使用Lombok,但不确定它是否会影响序列化格式。

How can I track down and fix the date serialization format to be ISO date String? 如何追踪并修复日期序列化格式为ISO日期字符串?

Here response example (start is LocalDateTime and I want to have it as ISO String): 这里的响应示例(start是LocalDateTime,我希望将它作为ISO String):

{
  "id": 3,
  "enabled": true,
  "outletId": 5,
  "reason": "hello",
  "start": [
    2019,
    9,
    10,
    10,
    42,
    11
  ],
  "status": "AVAILABLE"
}

Here the REST controller method response object: 这里是REST控制器方法的响应对象:

@Data
@Entity
@Table(indexes = { @Index(columnList = ("outletId"),name="outlet_id_index"), 
        @Index(columnList = ("start"),name="start_index"),
        @Index(columnList = ("outletId, start"),name="outlet_id_start_index")})
public class OutletChron extends BaseEntity {
    private Long outletId;
    private String reason;

    @DateTimeFormat(iso = ISO.DATE_TIME)
    private LocalDateTime start;
    @Enumerated(EnumType.STRING)
    @Column(length = 30)
    private OutletStatus status;
}

Here my POM: 我的POM在这里:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.banquets</groupId>
    <artifactId>Banquet</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Banquet</name>
    <description></description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> 
            </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 
            </dependency> -->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

UPDATE UPDATE

I build a new project just to test, and I found there String format was default for LocalDateTime mapping. 我构建了一个新项目来测试,我发现String格式是LocalDateTime映射的默认值。 I was able to track down that format changes once I configure swagger. 配置swagger后,我能够跟踪格式更改。 So without this swagger config I have String format: 所以没有这个swagger配置我有String格式:

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {

    @Autowired
    ServletContext servletContext;

    @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.demo"))
                .build();
    }

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

UPDATE this Swagger config seems works (Date format is String and I can access Swagger UI at http://localhost:8000/api/swagger-ui.html 更新此Swagger配置似乎有效(日期格式为String,我可以在http:// localhost:8000 / api / swagger-ui.html访问Swagger UI

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
}

Spring boot 2.x does not required to import JSR310 specifications as now its part of spring framework now so no need to import them and string formatting will automatically work. Spring引导2.x不需要导入JSR310规范,因为现在它是spring框架的一部分,所以不需要导入它们,字符串格式化将自动工作。

If you need to override some default configuration of spring boot then you need to implement WebMvcConfigurer instead of extending WebMvcConfigurationSupport . 如果需要覆盖spring boot的某些默认配置,则需要实现WebMvcConfigurer而不是扩展WebMvcConfigurationSupport

In your case, if you want to put static files somewhere else not in default resources folder then you might need to override addResourceHandlers and register paths. 在您的情况下,如果您想将静态文件放在默认资源文件夹中的其他位置,那么您可能需要覆盖addResourceHandlers和注册路径。

If resources in default path then not required and just removing extending WebMvcConfigurationSupport will work for default string formatting. 如果不需要默认路径中的资源,只需删除扩展WebMvcConfigurationSupport就可以用于默认字符串格式化。

UPDATED ANSWER: 更新的答案:

If you use WebMvcConfigurationSupport that means uts an indication that it shouldn't auto-configure Spring MVC, means default settings will not work and you have to define all things here by overriding its support methods. 如果您使用WebMvcConfigurationSupport意味着它不应该自动配置Spring MVC,则表示默认设置不起作用,您必须通过覆盖其支持方法来定义所有内容。 So instead of WebMvcConfigurationSupport implement WebMvcConfigurer instead. 因此,而不是WebMvcConfigurationSupport实现WebMvcConfigurer

Here is the updated config. 这是更新的配置。

@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {

    @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.demo"))
                .build();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

For me the following works: 对我来说,以下工作:

@JsonFormat(pattern = "dd.MM.yyyy HH:mm")
private LocalDateTime startTime;

This will print the date in a string format eg like 11.09.2018 15:44 这将以字符串格式打印日期,例如11.09.2018 15:44

Create object mapper manually 手动创建对象映射器

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();

    JavaTimeModule timeModule = new JavaTimeModule();
    mapper.registerModule(timeModule);

    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);

    return mapper;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM