Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@niwasawa

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

概要

  • 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 標準ライブラリの日時クラス

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
niwasawa
迷子になりがちな地図・位置情報系プログラマ。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?