green-creeper
green-creeper

Reputation: 316

JSON format for Generics in Play 2.x

my classes look like this

trait Value[T] {
  def get:T
}

I have implementations of this, for example

class StringValue(value : String) extends Value[String] {
  override def get : String = value
}

class NumberValue(value : Int) extends Value[Int] {
  override def get: Int = value
}

The problem is that I need to make jsonFormat for this types in order to save it to MongoDB.

I stucked for two days but still cannot figure out how to make it work

Upvotes: 1

Views: 2283

Answers (1)

cchantep
cchantep

Reputation: 9168

As for the provided .nullable which returns Reads for Option (generic type), you need to first enforce that the type parameter of Value is itself provided the required instances of Reads and Writes.

So for a generic Reads[Value[T]] the minimal def would be as bellow.

def valueReads[T](implicit underlying: Reads[T]): Reads[Value[T]] = ???

Similarily, for Writes[Value[T]] (or OWrites if it needs to be restricted to JSON object, and thus BSON document), the minimal definition would be as following.

def valueWrites[T](implicit underlying: Writes[T]): Writes[Value[T]] = ???
// or
def valueOWrites[T](implicit underlying: Writes[T]): OWrites[Value[T]] = ??? // don't define both as implicit to avoid conflict

Then the implementation depends on the way you want to represent Value[T] as JSON.

Considering the following JSON representation:

{ "_value": ... }

... then the Reads would be something as bellow.

implicit def valueReads[T](implicit underlying: Reads[T]): Reads[Value[T]] =
  Reads[Value[T]] { json =>
    (json \ "_value").validate(underlying).map { t: T =>
      Value(t)
    }
  }

Similarily, the OWrites[Value[T]] would be as following.

implicit def valueWrites[T](implicit underlying: Writes[T]): OWrites[Value[T]] =
  OWrites[Value[T]] { value => Json.obj("_value" -> value) }

Obviously, these implicits need to be in the implicit scope, either by being defined in the Value companion object, or by being explicitly imported if defined elsewhere.

Upvotes: 4

Related Questions