I am beginner with spray json application and I am using LocalDateTime as one of the parameter types in the case class.
import scala.collection.JavaConverters._
import org.apache.commons.imaging.Imaging
import org.joda.time.format.{DateTimeFormat, DateTimeFormatter}
import org.joda.time.{DateTime, LocalDateTime}
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import JodaDateTimeFormats._
import spray.json._
case class ExifMetadata(docName:String, exifOffset:Int, gpsInfo:Int, dateTimeOriginal:LocalDateTime,
gpsLatitudeRef:String, gpsLatitude:Double, gpsLongitudeRef:String, gpsLongitude:Double, gpsDateStamp:LocalDateTime)
trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
implicit val exifMetadataFormat = jsonFormat9(ExifMetadata)
}
However I keep getting the following error
could not find implicit value for evidence parameter of type JsonSupport.this.JF[org.joda.time.LocalDateTime]
First off: using JodaTime nowadays is discouraged by the authors:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
If you're still stuck on JDK 7 (you poor bastard), you should still prefer using ThreeTenBP, which provides an API almost identical to JSR-310. This would minimize upgrade friction.
With that out of the way: Spray does not provide JsonFormat
instances for JodaTime classes out of the box. You will have to write your own. Fortunately, that's not so hard.
How exactly you want to represent your LocalDateTime in JSON depends on your use case, but a standard ISO 8601 format makes sense.
import spray.json._
//prevent confusion with java.time.LocalDateTime
import org.joda.time.{LocalDateTime => JodaLocalDateTime}
implicit val jodaLocalDateTimeFormat: JsonFormat[JodaLocalDateTime] =
new JsonFormat[JodaLocalDateTime] {
override def write(obj: JodaLocalDateTime): JsValue = JsString(obj.toString)
override def read(json: JsValue): JodaLocalDateTime = json match {
case JsString(s) => Try(JodaLocalDateTime.parse(s)) match {
case Success(result) => result
case Failure(exception) =>
deserializationError(s"could not parse $s as Joda LocalDateTime", exception)
}
case notAJsString =>
deserializationError(s"expected a String but got a $notAJsString")
}
}
Make sure that you define this JsonFormat
at the top of your JsonSupport
trait. That way, it will be available to your other format(s).