0

As a disclaimer: I'm very new to Scala and functional programming in general.

I have the following classes:

case class A(
  field1: String,
  field2: DateTime
)

case class B(
  listOfStuff: Seq[A]
)

object A{
  def create(field1: String, field2: DateTime): A = A(field1, field2)
}

object B{
  def create(listOfStuff: Seq[A]): B = B(listOfStuff)
}

(The create() functions exist because I sometimes had issues in my code when using apply(). Let's ignore this, I doubt it's relevant.)

I get these objects in JSON format and I try to parse them using the Play-JSON library. An important aspect is that the list (Seq) can be missing from the JSON text, it's an optional field.

With that in mind, this is how I wrote that particular line:

private implicit val messageReader = (
    //...
    (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq()))
    //...
)(B.create _)

When compiling, I get the following error:

Error:(!line!, !column!) No Json deserializer found for type Seq[A]. Try to implement an implicit Reads or Format for this type.

From what I saw in this question, apparently you need to have an implicit instance of Reads[T] for every type T that is not part of the language (or something like that, did I mention I'm new to this?)

So I also added a secondary Reads[T] in the same scope, my code now looked like this:

private implicit val messageReader = (
    (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq()))
)(B.create _)

private implicit val anotherReader = (
    (__ \ "field1").read[String] and
    (__ \ "field2").read[String].map(org.joda.time.DateTime.parse)
)(A.create _)

However I still get that same error on the same line.

I feel like there's some very easy and obvious problem here, but I can't figure out what it is.

How do I fix this?

4
  • To be able to use parsers of Seq[T], parsers for T must be available Commented Jul 21, 2017 at 15:07
  • @cchantep Which is why I added the private implicit val anotherReader. It still doesn't work. Commented Jul 21, 2017 at 15:19
  • It must be available before (not as a later val) Commented Jul 21, 2017 at 15:34
  • @cchantep Your suggestion worked. I simply reversed their order and everything was fine. Post it as an answer and I will accept it ;) . Commented Jul 24, 2017 at 7:31

1 Answer 1

0

if B.create accepts a single argument then its reads can look like this:

private implicit val messageReader : Reads[B] =
  (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq())).map(B.create)
Sign up to request clarification or add additional context in comments.

1 Comment

Actually they're about 20 fields there, but of course I deleted them for the purpose of this question.

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.