Web系開発メモ

Java, C#, HTML, CSS, JavaScript のことなどを書いてます。

SpringBoot JSONの日時フォーマットとタイムゾーンを設定する方法

Spring Boot で、JSON に存在する日時(日付)のフォーマットとタイムゾーンを設定する方法を書いていきます。

目次

  1. バージョン
  2. アノテーションを使う方法
  3. 設定ファイルを使う方法
  4. コンフィギュレーションを使う方法
  5. 動作確認
  6. 動作確認の詳細

1. バージョン

動作確認で使用した製品のバージョンは以下の通りです。

2. アノテーションを使う方法

Jacksonのアノテーションで、フォーマットとタイムゾーンを設定することができます。

package org.example.model;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class Dates {

  @JsonFormat(pattern="yyyy/MM/dd HH:mm:ss", timezone="Asia/Tokyo")
  private Date date;

  @JsonFormat(pattern="yyyy/MM/dd HH:mm:ss", timezone="Asia/Tokyo")
  private Timestamp timestamp;

  @JsonFormat(pattern="yyyy/MM/dd HH:mm:ss", timezone="Asia/Tokyo")
  private LocalDateTime localDateTime;

  @JsonFormat(pattern="yyyy/MM/dd HH:mm:ss", timezone="Asia/Tokyo")
  private ZonedDateTime zonedDateTime;
}

3. 設定ファイルを使う方法

設定ファイルを使うと、Date型と Timestamp型のフォーマットとタイムゾーンを指定できます。

src/main/resources/application.properties

spring.jackson.date-format=yyyy/MM/dd HH:mm:ss
spring.jackson.time-zone=Asia/Tokyo

アノテーションは不要になります。

4. コンフィギュレーションを使う方法

LocalDateTime と ZonedDateTime は、コンフィギュレーションで設定できます。

src/main/java/org/example/config/JacksonConfig.java

package org.example.config;

import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

@Configuration
public class JacksonConfig {
  @Bean
  @SuppressWarnings("serial")
  public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return builder -> {
      // フォーマッターの作成
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
      DateTimeFormatter zonedFormatter = formatter.withZone(ZoneId.of("Asia/Tokyo"));
      // デシリアライズの設定
      builder.deserializers(new LocalDateTimeDeserializer(formatter));
      builder.deserializers(new StdDeserializer<>(ZonedDateTime.class) {
        @Override
        public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
          return ZonedDateTime.parse(p.getText(), zonedFormatter);
        }
      });
      // シリアライズの設定
      builder.serializers(new LocalDateTimeSerializer(formatter));
      builder.serializers(new StdSerializer<>(ZonedDateTime.class) {
        @Override
        public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
          gen.writeString(value.format(zonedFormatter));
        }
      });
    };
  }
}

アノテーションは不要になります。

5. 動作確認

何も設定しない場合の JSON は以下の通りです。

{
  "date":"2023-01-21T05:32:27.139+00:00",
  "timestamp":"2023-01-21T05:32:27.139+00:00",
  "localDateTime":"2023-01-21T14:32:27.1390874",
  "zonedDateTime":"2023-01-21T14:32:27.1390874+09:00"
}

上の設定をした場合は以下の通りです。

{
  "date":"2023/01/21 14:42:49",
  "timestamp":"2023/01/21 14:42:49",
  "localDateTime":"2023/01/21 14:42:49",
  "zonedDateTime":"2023/01/21 14:42:49"
}

6. 動作確認の詳細

6.1. モデル

以下のモデルを作成しました。

src/main/java/org/example/model/Dates.java

package org.example.model;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class Dates {
  private Date date;
  private Timestamp timestamp;
  private LocalDateTime localDateTime;
  private ZonedDateTime zonedDateTime;
}

6.2. コントローラー

モデルのプロパティを設定して、JSON を返すコントローラーを作成しました。

src/main/java/org/example/controller/DatesController.java

package org.example.controller;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;

import org.example.model.Dates;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DatesController {
  @GetMapping("/dates")
  public Dates get() {
    Dates dates = new Dates();
    dates.setDate(new Date());
    dates.setTimestamp(new Timestamp(
      System.currentTimeMillis()
    ));
    dates.setLocalDateTime(LocalDateTime.now());
    dates.setZonedDateTime(ZonedDateTime.now());
    return dates;
  }
}

6.3. 起動クラス

アプリを起動するクラスは以下の通りです。

src/main/java/org/example/SpringApp.java

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringApp {
  public static void main(String[] args) {
    SpringApplication.run(SpringApp.class, args);
  }
}

6.4. ビルドファイル

Maven のビルドファイルは以下の通りです。

pom.xml

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

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

  <groupId>org.example</groupId>
  <artifactId>spring-jackson-date-format</artifactId>
  <version>1.0.0</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>17</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
  </dependencies>

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

6.5. URL

アプリを起動して、以下の URL にアクセスします。

http://localhost:8080/dates