2

Using play-json 2.3 How do i parse this

{i: 0}

into this

case class A(i: Int, s: Seq[Int])

i would very much like to reuse Json.format macro

at the moment it gives me "missing path s"

UPD: i ended up writing a custom format and pimping it onto JsPath:

implicit class JsPathExtensions(path: JsPath) {
  //return mzero if the path is missing
  def lazyFormatNullableM[T: Monoid](f: => Format[T]): OFormat[T] = OFormat(path.lazyReadNullable(f).map(_.orZero), new OWrites[T] {
    override def writes(o: T) = path.lazyWriteNullable(f).writes(o.some)
  })
}

2 Answers 2

4

If the path is missing, I don't see any way to utilize the macro without changing the class. In which case, you can define Reads using json combinators and use the macro for Writes.

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val reads: Reads[A] = (
    (__ \ "i").read[Int] and 
    (__ \ "s").read[Seq[Int]].orElse(Reads.pure(Nil))
)(A.apply _)

implicit val writes: Writes[A] = Json.writes[A]

The json macros only cover a very limited range of use cases, and it's inevitable that you'll run into a case where you must write your own Reads or Writes.

Sign up to request clarification or add additional context in comments.

Comments

2

The easiest way to utilise the Json.format[A] macro would be to slightly alter your definition of A:

case class A(i: Int, s: Option[Seq[Int]])

The usage of an Option here is pretty clear and you can map over it and do lots of good things, but if you really want to treat s like it's an empty collection, you could enhance your case class a little more:

case class Foo(i: Int, s: Option[Seq[Int]]) {
  lazy val theSeq:Seq[Int] = s.getOrElse(Seq[Int]())
}

Now if you access theSeq, there is absolutely no difference between incoming JSON that omitted s and JSON that supplied an empty array for s.

2 Comments

yeah, i thought about that, but changing the class is not an option
Same problem, did you find a way to force Play.json to init empty seq instead of throwing error?

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.