概要
- 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
- GitHub - FasterXML/jackson-databind: General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
- JsonFormat (Jackson-annotations 2.12.1 API)
- ObjectMapper (jackson-databind 2.12.1 API)
- DateDeserializers (jackson-databind 2.12.1 API)
Jackson datatype: JSR310
Java 8 から導入された java.time パッケージの日時クラスに対応するためのパッケージ。
- GitHub - FasterXML/jackson-modules-java8: Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
- JavaTimeModule (Jackson datatype: JSR310 2.12.1 API)
- JSR310DateTimeDeserializerBase (Jackson datatype: JSR310 2.12.1 API)
- LocalDateTimeDeserializer (Jackson datatype: JSR310 2.12.1 API)
- jackson-modules-java8/JSR310DateTimeDeserializerBase.java at jackson-modules-java8-2.12.1 · FasterXML/jackson-modules-java8 · GitHub
日時パターン文字列
SimpleDateFormat はミリ秒までの精度、DateTimeFormatter はナノ秒までの精度。