aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/json.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/xyz/driver/core/json.scala')
-rw-r--r--src/main/scala/xyz/driver/core/json.scala84
1 files changed, 71 insertions, 13 deletions
diff --git a/src/main/scala/xyz/driver/core/json.scala b/src/main/scala/xyz/driver/core/json.scala
index 02a35fd..06a8837 100644
--- a/src/main/scala/xyz/driver/core/json.scala
+++ b/src/main/scala/xyz/driver/core/json.scala
@@ -1,23 +1,25 @@
package xyz.driver.core
import java.net.InetAddress
-import java.util.UUID
+import java.util.{TimeZone, UUID}
-import scala.reflect.runtime.universe._
-import scala.util.Try
+import akka.http.scaladsl.marshalling.{Marshaller, Marshalling}
import akka.http.scaladsl.model.Uri.Path
-import akka.http.scaladsl.server._
import akka.http.scaladsl.server.PathMatcher.{Matched, Unmatched}
-import akka.http.scaladsl.marshalling.{Marshaller, Marshalling}
+import akka.http.scaladsl.server._
import akka.http.scaladsl.unmarshalling.Unmarshaller
+import enumeratum._
+import eu.timepit.refined.api.{Refined, Validate}
+import eu.timepit.refined.collection.NonEmpty
+import eu.timepit.refined.refineV
import spray.json._
import xyz.driver.core.auth.AuthCredentials
import xyz.driver.core.date.{Date, DayOfWeek, Month}
import xyz.driver.core.domain.{Email, PhoneNumber}
-import xyz.driver.core.time.Time
-import eu.timepit.refined.refineV
-import eu.timepit.refined.api.{Refined, Validate}
-import eu.timepit.refined.collection.NonEmpty
+import xyz.driver.core.time.{Time, TimeOfDay}
+
+import scala.reflect.runtime.universe._
+import scala.util.Try
object json {
import DefaultJsonProtocol._
@@ -80,8 +82,34 @@ object json {
}
}
- implicit val dayOfWeekFormat: JsonFormat[DayOfWeek] =
- new EnumJsonFormat[DayOfWeek](DayOfWeek.All.map(w => w.toString -> w)(collection.breakOut): _*)
+ implicit object localTimeFormat extends JsonFormat[java.time.LocalTime] {
+ private val formatter = TimeOfDay.getFormatter
+ def read(json: JsValue): java.time.LocalTime = json match {
+ case JsString(chars) =>
+ java.time.LocalTime.parse(chars)
+ case _ => deserializationError(s"Expected time string got ${json.toString}")
+ }
+
+ def write(obj: java.time.LocalTime): JsValue = {
+ JsString(obj.format(formatter))
+ }
+ }
+
+ implicit object timeZoneFormat extends JsonFormat[java.util.TimeZone] {
+ override def write(obj: TimeZone): JsValue = {
+ JsString(obj.getID())
+ }
+
+ override def read(json: JsValue): TimeZone = json match {
+ case JsString(chars) =>
+ java.util.TimeZone.getTimeZone(chars)
+ case _ => deserializationError(s"Expected time zone string got ${json.toString}")
+ }
+ }
+
+ implicit val timeOfDayFormat: RootJsonFormat[TimeOfDay] = jsonFormat2(TimeOfDay.apply)
+
+ implicit val dayOfWeekFormat: JsonFormat[DayOfWeek] = new enumeratum.EnumJsonFormat(DayOfWeek)
implicit val dateFormat = new RootJsonFormat[Date] {
def write(date: Date) = JsString(date.toString)
@@ -109,9 +137,9 @@ object json {
}
implicit def revisionFromStringUnmarshaller[T]: Unmarshaller[String, Revision[T]] =
- Unmarshaller.strict[String, Revision[T]](Revision[T](_))
+ Unmarshaller.strict[String, Revision[T]](Revision[T])
- implicit def revisionFormat[T] = new RootJsonFormat[Revision[T]] {
+ implicit def revisionFormat[T]: RootJsonFormat[Revision[T]] = new RootJsonFormat[Revision[T]] {
def write(revision: Revision[T]) = JsString(revision.id.toString)
def read(value: JsValue): Revision[T] = value match {
@@ -159,6 +187,36 @@ object json {
JsString(obj.getHostAddress)
}
+ object enumeratum {
+
+ def enumUnmarshaller[T <: EnumEntry](enum: Enum[T]): Unmarshaller[String, T] =
+ Unmarshaller.strict { value =>
+ enum.withNameOption(value).getOrElse(unrecognizedValue(value, enum.values))
+ }
+
+ trait HasJsonFormat[T <: EnumEntry] { enum: Enum[T] =>
+
+ implicit val format: JsonFormat[T] = new EnumJsonFormat(enum)
+
+ implicit val unmarshaller: Unmarshaller[String, T] =
+ Unmarshaller.strict { value =>
+ enum.withNameOption(value).getOrElse(unrecognizedValue(value, enum.values))
+ }
+ }
+
+ class EnumJsonFormat[T <: EnumEntry](enum: Enum[T]) extends JsonFormat[T] {
+ override def read(json: JsValue): T = json match {
+ case JsString(name) => enum.withNameOption(name).getOrElse(unrecognizedValue(name, enum.values))
+ case _ => deserializationError("Expected string as enumeration value, but got " + json.toString)
+ }
+
+ override def write(obj: T): JsValue = JsString(obj.entryName)
+ }
+
+ private def unrecognizedValue(value: String, possibleValues: Seq[Any]): Nothing =
+ deserializationError(s"Unexpected value $value. Expected one of: ${possibleValues.mkString("[", ", ", "]")}")
+ }
+
class EnumJsonFormat[T](mapping: (String, T)*) extends RootJsonFormat[T] {
private val map = mapping.toMap