2

Dealing with an odd API that returns startDate and startTime as separate fields and I would prefer to use a single Joda DateTime field in my case class. I ended up not being able to do this but wanted to ask larger group if its possible. It seems 'and' should work to read in both fields as Strings and given I know timezone I think could combine these into single string and create instance of DateTime but I couldn't express that in an appropriate Reads.

I was messing around with these test objects/JSON:

 import org.joda.time.{ DateTime}
 import play.api.libs.functional.syntax._
 import play.api.libs.json.Reads._
 import play.api.libs.json._

 case class Example(startDate:String,startTime:String,name:String)
 case class Desired(date:DateTime,name:String)

 val json =Json.parse(
  """
   |{
   |"startDate": "2014-12-31",
   |"startTime": "12:43",
   |"name":"roger"
   |} 
   | """.stripMargin)

and I felt like this was on the right track but not certain:

val singleDateBuilder = (JsPath \ "startDate").read[String] and (JsPath \ "startTime").read[String]

but then I wasn't sure what to do next.

Got to this but can this be improved or should this be done differently?

val rawsm =
 """
  |{
  | "date": "2015-03-24",
  | "time": "12:00:00"
  |}
 """.stripMargin

val reader = (
  (__ \ "date").json.pick and
  (__ \ "time").json.pick
 ).tupled.map(t => new DateTime(t._1.as[String] + "T" +     t._2.as[String],DateTimeZone.UTC))

val single = Json.parse(rawsm).as[DateTime](reader)

1 Answer 1

3

After you combine reads with and, you can provide a function to produce the value you want from the individual reads results. For example:

val singleDateBuilder: Reads[DateTime] = 
    ((JsPath \ "startDate").read[String] and 
     (JsPath \ "startTime").read[String])(
        (date: String, time: String) => 
            new DateTime(date + "T" + time, DateTimeZone.UTC))
Sign up to request clarification or add additional context in comments.

1 Comment

+1. It's also worth remembering that Reads is monadic, so you can always just write something like for { d <- (__ \ 'date).read[String]; t <- (__ \ 'time).read[String] } yield new DateTime(s"${d}T$t", DateTimeZone.UTC) as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.