Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala play json No unapply or unapplySeq function found

This JSON automated mapping example from the play documentation fails. why? https://www.playframework.com/documentation/2.5.x/ScalaJsonAutomated

libraryDependencies += "com.typesafe.play" %% "play" % "2.5.0"
---
import play.api.libs.json._
case class Resident(name: String, age: Int, role: Option[String])
implicit val residentWrites = Json.writes[Resident]
println(Json.toJson(Resident("john", 33, None)))
---
Error: No unapply or unapplySeq function found
      implicit val residentWrites = Json.writes[Resident]
like image 842
David Portabella Avatar asked Apr 28 '16 21:04

David Portabella


1 Answers

The problematic code looked more or less like that:

import play.api.libs.json._

object Test {
  def main(args: Array[String]): Unit = {
    case class Resident(name: String, age: Int, role: Option[String])
    implicit val residentWrites = Json.writes[Resident]
    println(Json.toJson(Resident("john", 33, None)))
  }
}

The issue here was that this macro apparently doesn't work for classes defined inside methods. This is not a troubling limitation though as we rather don't do this sort of things.

To resolve issue class def can be moved somewhere else, like object level

object Test {
  case class Resident(name: String, age: Int, role: Option[String])

  def main(args: Array[String]): Unit = {
    implicit val residentWrites = Json.writes[Resident]
    println(Json.toJson(Resident("john", 33, None)))
  }
}

or file level

case class Resident(name: String, age: Int, role: Option[String])

object Test {
  def main(args: Array[String]): Unit = {
    implicit val residentWrites = Json.writes[Resident]
    println(Json.toJson(Resident("john", 33, None)))
  }
}

I understand that this was only for test purposes to see minimal example, but I will still mention how we usually define classes with Writes.

object Resident {
  implicit val residentWrites = Json.writes[Resident]
}

case class Resident(name: String, age: Int, role: Option[String])

This way, whenever you import the Resident, its writes will be in the implicit scope.

like image 97
Łukasz Avatar answered Nov 15 '22 22:11

Łukasz