[play2.1][scala][JSON] : writing a Reads/Writes for a single field case class

2398 views
Skip to first unread message

Pascal Voitot Dev

unread,
Jan 11, 2013, 8:45:42 AM1/11/13
to play-fr...@googlegroups.com
Hello again,

A few people have encountered the case of Json macro failing for single field case class.
This is not a bug but a limitation of current Macro implementation.

But there is a workaround to write it relatively simply using Reads.map/Writes.contramap/Format.invmap function which can be really useful if you don't know them.

Everything is explained in this ticket:
https://play.lighthouseapp.com/projects/82401-play-20/tickets/918-play-21-json-issues#ticket-918-4

regards
Pascal

Rogério Yokomizo

unread,
Jun 25, 2014, 8:05:55 PM6/25/14
to play-fr...@googlegroups.com
Hello

The original ticket was deprecated. Is there a new link to it?

regards

Rogério

Pascal Voitot Dev

unread,
Jun 26, 2014, 2:30:51 AM6/26/14
to play-fr...@googlegroups.com
I can't find it!
If you search in google group for "reads case class single field" you should find a few hints.

but this is very simple
with :
case class Foo(foo: String)

you must use :
(__ \ "foo").read[String].map(Foo(_))

(__ \ "foo").write[String].contramap((f: Foo) => f.foo)

For Format, it's invmap mixing both...

regards
Pascal


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Henry Katz

unread,
Jan 14, 2019, 1:40:34 PM1/14/19
to Play Framework [deprecated]
Expanding on this, if the single field case class were a higher kind such as

case class Foo(foo: List[String])

everything below still works just fine:

(__ \ "foo").read[List[String]].map(Foo(_))

but say you were trying to validate that field with a uniqueitems validation function such as:

  def uniqueItems[String](isUnique: Boolean)(implicit tag: TypeTag[String], r: Reads[List[String]]): Reads[List[String]] = {
    Reads.of[List[String]].filter(ValidationError(uniqueItemsJsonValidationError))({ items =>
      if (isUnique) items.size == items.distinct.size
      else true
    })
  }

which would change the read to

(__ \ "foo").read[List[String]](uniqueItems(true)).map(Foo(_))

giving a compile error as there is no implicit for a List[String] though we know play can deserialize a String:

No Json deserializer found for type List[String]. Try to implement an implicit Reads or Format for this type.
[error]   implicit val dinosaurReader: Reads[Dinosaur] = ((JsPath \ "friends").read[List[String]](uniqueItems(true))).map(Dinosaur)
[error]                                                                                                                                               ^

Tim Moore

unread,
Jan 14, 2019, 4:55:50 PM1/14/19
to play-fr...@googlegroups.com
The problem could be that you've defined a type variable named "String", which would shadow the built in String type and is probably not what you are intending:

def uniqueItems[String](isUnique: Boolean)(implicit tag: TypeTag[String], r: Reads[List[String]])

It's probably this "String" that the error refers to.

Best,
Tim

--
Please join our new forum at https://discuss.playframework.com!
The play-framework Google Group will soon be put into read-only mode.
For details, see https://blog.playframework.com/introducing-discuss-playframework-com/.
---
You received this message because you are subscribed to the Google Groups "Play Framework [deprecated]" group.

To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
Tim Moore
Sr. Manager Engineering and Product Management, Lightbend, Inc.
Reply all
Reply to author
Forward
0 new messages