Search code examples
scalatypesmarshalling

How to create generic implicit conversions for json marshalling


I want to limit the construction of a case class to certain types and then be able to marshall that data back and forth.

For example, let's say I have a "home" case class that takes in a "kind" argument. I want to restrict the "kind" argument to a list of approved housing types, e.g., Apartment, Condo, etc.

object Home {
  // this will create an implicit conversion to json object
  implicit lazy val jsFormat = Jsonx.formatCaseClass[Home]
}

case class Home(owner: String, kind: HousingType)

What I need now is a way to marshall the various child types of HousingType. For example, here are some relationships:

trait HousingType

case object Apartment extends HousingType

case object Condo extends HousingType

Predictably, attempting to use this without specifying an implicit conversion yields the following error:

"could not find implicit value for parameter helper: ... HousingType"

Is there a way to create a generic implicit conversion for this?


Solution

  • You have to specify how your JSON marshaller has to transform your case object, as you have case class, it's quite simple for JSON marshaller to follow default behavior - take JSON field names from a case class and their type.

    You need to indicate how to marshall/unmarshall case object directly, for instance via an implicit conversion.

      implicit object HousingTypeMarshaller extends Writes[HousingType] {
        def writes(housingType: HousingType) = housingType match {
          case Apartment => Json.toJson("Apartment")
          case Condo => Json.toJson("Condo")
        }
      }
    

    p.s. I use usual play.json in this example because I didn't find any reason to use Jsonx, suggest you faced a limitation on 22 fields with Play Json, usual Play Json is suitable for this situation with case object.