Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonWriter and JsonReader for java.time #293

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions modules/core/src/main/scala/tethys/readers/KeyReader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,28 @@ object KeyReader {
implicit lazy val longKeyReader: KeyReader[Long] = new KeyReader[Long] {
override def read(s: String)(implicit fieldName: FieldName): Long = s.toLong
}

implicit lazy val instantKeyReader: KeyReader[java.time.Instant] = new KeyReader[java.time.Instant] {
override def read(s: String)(implicit fieldName: FieldName): java.time.Instant = java.time.Instant.parse(s)
}

implicit lazy val localDateKeyReader: KeyReader[java.time.LocalDate] = new KeyReader[java.time.LocalDate] {
override def read(s: String)(implicit fieldName: FieldName): java.time.LocalDate =
java.time.LocalDate.parse(s, java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
}

implicit lazy val localDateTimeKeyReader: KeyReader[java.time.LocalDateTime] = new KeyReader[java.time.LocalDateTime] {
override def read(s: String)(implicit fieldName: FieldName): java.time.LocalDateTime =
java.time.LocalDateTime.parse(s, java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)
}

implicit lazy val offsetDateTimeKeyReader: KeyReader[java.time.OffsetDateTime] = new KeyReader[java.time.OffsetDateTime] {
override def read(s: String)(implicit fieldName: FieldName): java.time.OffsetDateTime =
java.time.OffsetDateTime.parse(s, java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)
}

implicit lazy val zonedDateTimeKeyReader: KeyReader[java.time.ZonedDateTime] = new KeyReader[java.time.ZonedDateTime] {
override def read(s: String)(implicit fieldName: FieldName): java.time.ZonedDateTime =
java.time.ZonedDateTime.parse(s, java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,14 @@ trait AllJsonReaders extends OptionReaders {
implicit lazy val javaBigIntegerReader: JsonReader[java.math.BigInteger] = bigIntReader.map(_.bigInteger)
implicit lazy val javaUUIDReader: JsonReader[java.util.UUID] = stringReader.map(java.util.UUID.fromString(_))

implicit lazy val javaInstantReader: JsonReader[java.time.Instant] = stringReader.map(java.time.Instant.parse)
implicit lazy val javaLocalDateReader: JsonReader[java.time.LocalDate] =
stringReader.map(java.time.LocalDate.parse(_, java.time.format.DateTimeFormatter.ISO_LOCAL_DATE))
implicit lazy val javaLocalDateTimeReader: JsonReader[java.time.LocalDateTime] =
stringReader.map(java.time.LocalDateTime.parse(_, java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME))
implicit lazy val javaOffsetDateTimeReader: JsonReader[java.time.OffsetDateTime] =
stringReader.map(java.time.OffsetDateTime.parse(_, java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME))
implicit lazy val javaZonedDateTimeReader: JsonReader[java.time.ZonedDateTime] =
stringReader.map(java.time.ZonedDateTime.parse(_, java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME))

}
15 changes: 15 additions & 0 deletions modules/core/src/main/scala/tethys/writers/KeyWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,19 @@ object KeyWriter {
implicit lazy val intKeyWriter: KeyWriter[Int] = _.toString

implicit lazy val longKeyWriter: KeyWriter[Long] = _.toString

implicit lazy val instantKeyWriter: KeyWriter[java.time.Instant] = _.toString

implicit lazy val localDateKeyWriter: KeyWriter[java.time.LocalDate] =
_.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)

implicit lazy val localDateTimeKeyWriter: KeyWriter[java.time.LocalDateTime] =
_.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)

implicit lazy val offsetDateTimeKeyWriter
: KeyWriter[java.time.OffsetDateTime] =
_.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)

implicit lazy val zonedDateTimeKeyWriter: KeyWriter[java.time.ZonedDateTime] =
_.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME)
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,34 @@ trait AllJsonWriters extends OptionWriters with EitherWriters {
implicit lazy val nullWriter: JsonWriter[Null] = new JsonWriter[Null] {
override def write(value: Null, tokenWriter: TokenWriter): Unit = tokenWriter.writeNull()
}

implicit lazy val instantWriter: JsonWriter[java.time.Instant] =
new JsonWriter[java.time.Instant] {
override def write(value: java.time.Instant, tokenWriter: TokenWriter): Unit =
tokenWriter.writeString(value.toString)
}

implicit lazy val localDateWriter: JsonWriter[java.time.LocalDate] =
new JsonWriter[java.time.LocalDate] {
override def write(value: java.time.LocalDate, tokenWriter: TokenWriter): Unit =
tokenWriter.writeString(value.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE))
}

implicit lazy val localDateTimeWriter: JsonWriter[java.time.LocalDateTime] =
new JsonWriter[java.time.LocalDateTime] {
override def write(value: java.time.LocalDateTime, tokenWriter: TokenWriter): Unit =
tokenWriter.writeString(value.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME))
}

implicit lazy val offsetDateTimeWriter: JsonWriter[java.time.OffsetDateTime] =
new JsonWriter[java.time.OffsetDateTime] {
override def write(value: java.time.OffsetDateTime, tokenWriter: TokenWriter): Unit =
tokenWriter.writeString(value.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME))
}

implicit lazy val zonedDateTimeWriter: JsonWriter[java.time.ZonedDateTime] =
new JsonWriter[java.time.ZonedDateTime] {
override def write(value: java.time.ZonedDateTime, tokenWriter: TokenWriter): Unit =
tokenWriter.writeString(value.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import scala.reflect.ClassTag

class DefaultReadersTest extends AnyFlatSpec {
private val randomUUID = java.util.UUID.randomUUID()
private val instantNow = java.time.Instant.now()
private val localDateNow = java.time.LocalDate.now()
private val localDateTimeNow = java.time.LocalDateTime.now()
private val offsetDateTimeNow = java.time.OffsetDateTime.now()
private val zonedDateTimeNow = java.time.ZonedDateTime.now()

private def test[A](result: A)(implicit jsonReader: JsonReader[A], ct: ClassTag[A]): TestDefinition[A] = {
TestDefinition(result, jsonReader, ct.toString())
Expand All @@ -36,6 +41,15 @@ class DefaultReadersTest extends AnyFlatSpec {
test(List[Int](), "Seq.empty") -> arr(),
test(Map("a" -> 1, "b" -> 2)) -> obj("a" -> 1, "b" -> 2),
test(Map(randomUUID -> 1),"Map with UUID keys") -> obj(randomUUID.toString -> 1),
test(Map(instantNow -> 1), "Map with Instant keys") -> obj(instantNow.toString -> 1),
test(Map(localDateNow -> 1), "Map with LocalDate keys") ->
obj(localDateNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE) -> 1),
test(Map(localDateTimeNow -> 1), "Map with LocalDateTime keys") ->
obj(localDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME) -> 1),
test(Map(offsetDateTimeNow -> 1), "Map with OffsetDateTime keys") ->
obj(offsetDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME) -> 1),
test(Map(zonedDateTimeNow -> 1), "Map with ZonedDateTime keys") ->
obj(zonedDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME) -> 1),
dos65 marked this conversation as resolved.
Show resolved Hide resolved
test(Map(1L -> 1), "Map with Long keys") -> obj("1" -> 1),
test(Map(1 -> 1), "Map with Int keys") -> obj("1" -> 1),
test(Option(1), "Option.nonEmpty") -> value(1),
Expand All @@ -47,7 +61,12 @@ class DefaultReadersTest extends AnyFlatSpec {
test(1d: java.lang.Double) -> value(1d),
test(java.math.BigDecimal.valueOf(1)) -> value(1: BigDecimal),
test(java.math.BigInteger.valueOf(1)) -> value(1: BigInt),
test(randomUUID) -> value(randomUUID.toString)
test(randomUUID) -> value(randomUUID.toString),
test(instantNow) -> value(instantNow.toString),
test(localDateNow) -> value(localDateNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)),
test(localDateTimeNow) -> value(localDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)),
test(offsetDateTimeNow) -> value(offsetDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)),
test(zonedDateTimeNow) -> value(zonedDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME))
)

behavior of "Default readers"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import scala.reflect.ClassTag

class DefaultWritersTest extends AnyFlatSpec {
private val randomUUID = java.util.UUID.randomUUID()
private val instantNow = java.time.Instant.now()
private val localDateNow = java.time.LocalDate.now()
private val localDateTimeNow = java.time.LocalDateTime.now()
private val offsetDateTimeNow = java.time.OffsetDateTime.now()
private val zonedDateTimeNow = java.time.ZonedDateTime.now()

private def test[A](value: A)(implicit jsonWriter: JsonWriter[A], ct: ClassTag[A]): TestDefinition[A] = {
TestDefinition(value, jsonWriter, ct.toString())
Expand All @@ -38,6 +43,15 @@ class DefaultWritersTest extends AnyFlatSpec {
test(Map(randomUUID -> 1),"Map with UUID keys") -> obj(randomUUID.toString -> 1),
test(Map(1L -> 1), "Map with Long keys") -> obj("1" -> 1),
test(Map(1 -> 1), "Map with Int keys") -> obj("1" -> 1),
test(Map(instantNow -> 1), "Map with Instant keys") -> obj(instantNow.toString -> 1),
test(Map(localDateNow -> 1), "Map with LocalDate keys") ->
obj(localDateNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE) -> 1),
test(Map(localDateTimeNow -> 1), "Map with LocalDateTime keys") ->
obj(localDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME) -> 1),
test(Map(offsetDateTimeNow -> 1), "Map with OffsetDateTime keys") ->
obj(offsetDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME) -> 1),
test(Map(zonedDateTimeNow -> 1), "Map with ZonedDateTime keys") ->
obj(zonedDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME) -> 1),
dos65 marked this conversation as resolved.
Show resolved Hide resolved
test(Option(1), "Option.nonEmpty") -> value(1),
test(Option.empty[Int], "Option.empty") -> List(NullValueNode),
test(Right(1): Either[String, Int], "Either.right") -> value(1),
Expand All @@ -49,7 +63,12 @@ class DefaultWritersTest extends AnyFlatSpec {
test(1d: java.lang.Double) -> value(1d),
test(java.math.BigDecimal.valueOf(1)) -> value(1: BigDecimal),
test(java.math.BigInteger.valueOf(1)) -> value(1: BigInt),
test(randomUUID) -> value(randomUUID.toString)
test(randomUUID) -> value(randomUUID.toString),
test(instantNow) -> value(instantNow.toString),
test(localDateNow) -> value(localDateNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)),
test(localDateTimeNow) -> value(localDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)),
test(offsetDateTimeNow) -> value(offsetDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)),
test(zonedDateTimeNow) -> value(zonedDateTimeNow.format(java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME))
)

behavior of "Default writers"
Expand Down
Loading