0
votes

I'm new to Scala and my question is about Json serialization using play (2.5) for Joda's optional value My Inputs: 1.

import org.joda.time.LocalDateTime
     case class User(
                     name: String, 
                     lastLogin: Option[LocalDateTime])
    object User {
      implicit val serializers = JsonSerializers
      implicit val UserFormat: Format[User] = Format(serializers.UserReads, serializers.UserWrites)
    }
  1. Serializers

    import com.dtos.{User}
    import org.joda.time.LocalDateTime
    import org.joda.time.format.DateTimeFormat
    import play.api.libs.json._
    import play.api.libs.functional.syntax._
    object JsonSerializers {
      val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
    
      implicit val UserReads: Reads[User] = (
        (JsPath \ "name").read [String] and
          (JsPath \ "active").read [Boolean] and
          (JsPath \\ "$ldt").read[LocalDateTime]
        )(User.apply _)
    
      implicit val UserWrites: Writes[User] = (
        (JsPath \ "name").write [String] and
          (JsPath \ "active").write [Boolean] and
          (JsPath \ "lastLogin" \ "$ldt") .write [LocalDateTime]
        )(unlift (User.unapply))
    }
    
  2. Test Object:

    object MainTest extends App {    
      val value: JsValue = Json.parse("{ \"name\" : \"hello\" , \"lastLogin\" : {\"$ldt\":\"2018-09-09T11:06:27.655\"} }")
      println("First Output:")
      println(Json.toJson(new MyUser("user", LocalDateTime.now)))
      println("Second Output:")
      println(Json.fromJson(value))    
    }
    

Questions: 1. How to manage Option value during UserReads/UserWrites? I'm getting the following Error:

overloaded method value apply with alternatives: [B](f: B => (String, Boolean, org.joda.time.LocalDateTime))(implicit fu: play.api.libs.functional.ContravariantFunctor[play.api.libs.json.Reads])play.api.libs.json.Reads[B] [B](f: (String, Boolean, org.joda.time.LocalDateTime) => B)(implicit fu: play.api.libs.functional.Functor[play.api.libs.json.Reads])play.api.libs.json.Reads[B] cannot be applied to ((String, Boolean, Option[org.joda.time.LocalDateTime]) => com.dtos.User) (JsPath \ "active").read [Boolean] and

  1. can't make it work for the input Json Structure of User, when $ldt is a sub element of lastLogin:

     val value: JsValue = Json.parse("{ \"name\" : \"hello\" , \"lastLogin\" : {\"$ldt\":\"2018-09-09T11:06:27.655\"} }")
    
    (means User is defined by:
    "name\":\"myName\",
    \"active\":true,
    \"lastLogin\":{\"$ldt\":\"2018-09-09T11:06:27.655\"}
    }
    )
    
1
Have a look at readOpt and writeOptcchantep
@cchantep, that's what i was missing!! In my case it was about readNullable & writeNullable - worked as a magic.nikabu

1 Answers

0
votes

I think what you are missing is the serializer Format[LocalDateTime].

Option is supported out of the box.

Taken from another Stackoverflow answer:

import org.joda.time.LocalDateTime
import org.joda.time.format.ISODateTimeFormat

implicit val readsJodaLocalDateTime = Reads[LocalDateTime](js =>
  js.validate[String].map[LocalDateTime](dtString =>
    LocalDateTime.parse(dtString, ISODateTimeFormat.basicDateTime())
  )
)

See here the whole answer: custom-jodatime-serializer-using-play-frameworks-json-library

By the way for case classes you can add a serializer like this:

object User {
  implicit val jsonFormat: Format[User] = Json.format[User]
}