LoginSignup
4
3

More than 3 years have passed since last update.

Java + Jackson Databind で JSON 日時文字列とオブジェクトを相互変換する

Posted at

概要

  • Java + Jackson Databind で JSON の日付・時刻を表す文字列と Java オブジェクトを相互変換するサンプルコードを示す
  • 環境: Java 15 (AdoptOpenJDK 15.0.2+7) + Jackson Databind 2.12.1 + Jackson datatype: JSR310 2.12.1 + Gradle 6.8.2 + macOS Catalina

サンプルコード

ファイル一覧

├── build.gradle
└── src
    └── main
        └── java
            ├── Sample.java
            └── SampleData.java

build.gradle

plugins {
  id 'application'
  id 'java'
}

sourceCompatibility = JavaVersion.VERSION_15

application {
  mainClass = 'Sample'
}

repositories {
  mavenCentral()
}

dependencies {
  // Jackson Databind
  implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.1'

  // java.time 系オブジェクトとの変換に必要
  // Add-on module to support JSR-310 (Java 8 Date & Time API) data types.
  implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.1'

  // Lombok
  compileOnly 'org.projectlombok:lombok:1.18.18'
  annotationProcessor 'org.projectlombok:lombok:1.18.18'
}

src/main/java/Sample.java

Jackson Databind を使用して JSON 文字列と Java オブジェクトの相互変換をするクラス。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.IOException;
import java.io.StringWriter;

public class Sample {

  public static void main(String[] args) throws IOException {

    // 元データの JSON
    // 変換する Java 型によって使用するパースする際のフォーマッタ (SimpleDateFormat と DateTimeFormatter) が異なる
    // フォーマッタによって秒の小数部の精度 (ミリ秒・ナノ秒) が異なる
    String json = """
      {
        "utilDate"             : "2001-12-31 23:59:59.789",
        "utilDateIso8601"      : "2001-12-31T23:59:59.789+09:00",
        "utilCalendar"         : "2001-12-31 23:59:59.789",
        "utilCalendarIso8601"  : "2001-12-31T23:59:59.789+09:00",
        "sqlDate"              : "2001-12-31",
        "sqlTime"              :            "23:59:59",
        "sqlTimestamp"         : "2001-12-31 23:59:59.789",
        "sqlTimestampIso8601"  : "2001-12-31T23:59:59.789+09:00",
        "localDate"            : "2001-12-31",
        "localTime"            :            "23:59:59.123456789",
        "localDateTime"        : "2001-12-31 23:59:59.123456789",
        "localDateTimeIso8601" : "2001-12-31T23:59:59.123456789",
        "zonedDateTimeIso8601" : "2001-12-31T23:59:59.123456789+09:00"
      }""";
    System.out.println();
    System.out.println("元データの JSON");
    System.out.println(json);

    // JSON 文字列をオブジェクトに変換
    SampleData foo = new ObjectMapper()
      .registerModule(new JavaTimeModule()) // JSR-310 サポート
      .readValue(json, SampleData.class);
    System.out.println();
    System.out.println("JSON から変換したオブジェクト");
    System.out.println(foo.toString().replace(", ", ",\n")); // 読みやすく改行

    // オブジェクトを JSON 文字列に変換
    StringWriter writer = new StringWriter();
    new ObjectMapper()
      .registerModule(new JavaTimeModule()) // JSR-310 サポート
      .writerWithDefaultPrettyPrinter() // 読みやすく整形
      .writeValue(writer, foo);
    System.out.println();
    System.out.println("オブジェクトから変換した JSON");
    System.out.println(writer.toString());
  }
}

src/main/java/SampleData.java

JSON マッピングするデータを表すクラス。

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;

@Data
public class SampleData {

  // java.util 系に適用する pattern は SimpleDateFormat 互換

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "Asia/Tokyo")
  private java.util.Date utilDate;

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "Asia/Tokyo")
  private java.util.Date utilDateIso8601;

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "Asia/Tokyo")
  private java.util.Calendar utilCalendar;

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "Asia/Tokyo")
  private java.util.Calendar utilCalendarIso8601;

  // java.sql 系に適用する pattern は SimpleDateFormat 互換

  @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Tokyo")
  private java.sql.Date sqlDate;

  @JsonFormat(pattern = "HH:mm:ss", timezone = "Asia/Tokyo")
  private java.sql.Time sqlTime;

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "Asia/Tokyo")
  private java.sql.Timestamp sqlTimestamp;

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "Asia/Tokyo")
  private java.sql.Timestamp sqlTimestampIso8601;

  // java.time 系に適用する pattern は DateTimeFormatter 互換

  @JsonFormat(pattern = "yyyy-MM-dd")
  private LocalDate localDate;

  @JsonFormat(pattern = "HH:mm:ss.nnnnnnnnn")
  private LocalTime localTime;

  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.nnnnnnnnn")
  private LocalDateTime localDateTime;

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.nnnnnnnnn")
  private LocalDateTime localDateTimeIso8601;

  @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.nnnnnnnnnxxx", timezone = "Asia/Tokyo")
  private ZonedDateTime zonedDateTimeIso8601;
}

サンプルコードの実行結果

$ gradle run

> Task :run

元データの JSON
{
  "utilDate"             : "2001-12-31 23:59:59.789",
  "utilDateIso8601"      : "2001-12-31T23:59:59.789+09:00",
  "utilCalendar"         : "2001-12-31 23:59:59.789",
  "utilCalendarIso8601"  : "2001-12-31T23:59:59.789+09:00",
  "sqlDate"              : "2001-12-31",
  "sqlTime"              :            "23:59:59",
  "sqlTimestamp"         : "2001-12-31 23:59:59.789",
  "sqlTimestampIso8601"  : "2001-12-31T23:59:59.789+09:00",
  "localDate"            : "2001-12-31",
  "localTime"            :            "23:59:59.123456789",
  "localDateTime"        : "2001-12-31 23:59:59.123456789",
  "localDateTimeIso8601" : "2001-12-31T23:59:59.123456789",
  "zonedDateTimeIso8601" : "2001-12-31T23:59:59.123456789+09:00"
}

JSON から変換したオブジェクト
SampleData(utilDate=Mon Dec 31 23:59:59 JST 2001,
utilDateIso8601=Mon Dec 31 23:59:59 JST 2001,
utilCalendar=java.util.GregorianCalendar[time=1009810799789,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2001,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=6,DAY_OF_MONTH=31,DAY_OF_YEAR=365,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MINUTE=59,SECOND=59,MILLISECOND=789,ZONE_OFFSET=0,DST_OFFSET=0],
utilCalendarIso8601=java.util.GregorianCalendar[time=1009810799789,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2001,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=6,DAY_OF_MONTH=31,DAY_OF_YEAR=365,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MINUTE=59,SECOND=59,MILLISECOND=789,ZONE_OFFSET=0,DST_OFFSET=0],
sqlDate=2001-12-31,
sqlTime=23:59:59,
sqlTimestamp=2001-12-31 23:59:59.789,
sqlTimestampIso8601=2001-12-31 23:59:59.789,
localDate=2001-12-31,
localTime=23:59:59.123456789,
localDateTime=2001-12-31T23:59:59.123456789,
localDateTimeIso8601=2001-12-31T23:59:59.123456789,
zonedDateTimeIso8601=2001-12-31T14:59:59.123456789Z[UTC])

オブジェクトから変換した JSON
{
  "utilDate" : "2001-12-31 23:59:59.789",
  "utilDateIso8601" : "2001-12-31T23:59:59.789+09:00",
  "utilCalendar" : "2001-12-31 23:59:59.789",
  "utilCalendarIso8601" : "2001-12-31T23:59:59.789+09:00",
  "sqlDate" : "2001-12-31",
  "sqlTime" : "23:59:59",
  "sqlTimestamp" : "2001-12-31 23:59:59.789",
  "sqlTimestampIso8601" : "2001-12-31T23:59:59.789+09:00",
  "localDate" : "2001-12-31",
  "localTime" : "23:59:59.123456789",
  "localDateTime" : "2001-12-31 23:59:59.123456789",
  "localDateTimeIso8601" : "2001-12-31T23:59:59.123456789",
  "zonedDateTimeIso8601" : "2001-12-31T23:59:59.123456789+09:00"
}

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

参考資料

Jackson Core Databind

Jackson datatype: JSR310

Java 8 から導入された java.time パッケージの日時クラスに対応するためのパッケージ。

日時パターン文字列

SimpleDateFormat はミリ秒までの精度、DateTimeFormatter はナノ秒までの精度。

Java 標準ライブラリの日時クラス

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3