Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Framework: How to define a writable object in scala?

Using Play, I have an object called RepositoryMetadata. I want to use that object in a method called post. The definition of that method is given below.

def post[T](body: T)(implicit wrt: Writeable[T], ct: ContentTypeOf[T]): Future[WSResponse].

How do I make the object RepositoryMetadata into Writeable.

like image 827
odbhut.shei.chhele Avatar asked Dec 15 '22 07:12

odbhut.shei.chhele


2 Answers

For anyone interested in, I've run into a similar issue when using Play's WSClient. The version which I'm currently using (2.5.3) has the following signature:

def post[T](body: T)(implicit wrt: Writeable[T]): Future[WSResponse]

If you happen to need to post the payload as a json (as long as you already have a play.api.libs.json.Writes converter defined for your class) you could have something like below:

import play.api.http.{ContentTypeOf, ContentTypes, Writeable}
import play.api.libs.json.Writes
import play.api.mvc.Codec

trait WritableImplicits {
  implicit def jsonWritable[A](implicit writes: Writes[A], codec: Codec): Writeable[A] = {
    implicit val contentType = ContentTypeOf[A](Some(ContentTypes.JSON))
    val transform = Writeable.writeableOf_JsValue.transform compose (writes.writes _)
    Writeable(transform)
  }
}

object WritableImplicits extends WritableImplicits

and then

import WritableImplicits._
...
val metadata: RepositoryMetadata = ???
wsClient.url(url).post(metadata)
...

And that should be it!

NOTE: If you don't have an implicit Writes defined in scope, you could just do the following:

import play.api.libs.json._

object RepositoryMetadata {
   implicit val repositoryMetadataWrites = Json.writes[RepositoryMetadata]  
}
like image 148
lregnier Avatar answered Dec 21 '22 12:12

lregnier


You will need to include two implicits:

import play.api.http._
import play.api.mvc._

implicit def writeable(implicit codec: Codec): Writeable[RepositoryMetadata] = {
  // assuming RepositoryMetadata has a .toString
  Writeable(data => codec.encode(data.toString))
}

implicit def contentType(implicit codec: Codec): ContentTypeOf[RepoositoryMetadata] = {
  // for text/plain
  ContentTypeOf(Some(ContentTypes.TEXT))
}

the two imports import the following:

play.api.http.ContentTypes
play.api.http.ContentTypeOf
play.api.http.Writeable
play.api.mvc.Codec
like image 36
bjfletcher Avatar answered Dec 21 '22 12:12

bjfletcher