Skip to content

Instantly share code, notes, and snippets.

@erikfried
Created June 3, 2013 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikfried/5701409 to your computer and use it in GitHub Desktop.
Save erikfried/5701409 to your computer and use it in GitHub Desktop.
Automagic content negotiation with playframework (version >= 2.1). If called with Accept: application/json => { "firstName": "Erik", "surName": "Fried", "age": 34 } Accept: text/xml => <person> <firstName>Erik</firstName> <surName>Fried</surName> <age>34</age> </person>
package controllers
import play.api.mvc._
import play.api.libs.json.{Writes, Json}
import test.PersonRepository
import scala.xml.Elem
object PersonResource extends Controller with ContentNegotiation {
def getPerson(id: Int) = Action { implicit request =>
//The ContentNegotiation trait provides the XmlOrJson function.
XmlOrJson {
PersonRepository.get(id)
}
}
}
// Define a base "interface" for all classes that can be serialized to XML.
trait XmlSerializable {
def toXML: Elem
}
trait ContentNegotiation {
//Self type annotation -> trait must be mixed in into Controller (thus, has access to render, Accepts and Ok)
self : Controller =>
//Serializes the provided value according to the Accept headers of the (implicitly) provided request
def XmlOrJson[A <: XmlSerializable](value: A)(implicit request: Request[AnyContent], writes: Writes[A]) : Result = {
render {
case Accepts.Xml() => Ok(value.toXML)
case Accepts.Json() => Ok(Json.toJson(value))
}
}
}
package test
import play.api.libs.json.Json
import controllers.XmlSerializable
case class Person(firstName: String, surName: String, age: Int) extends XmlSerializable{
//The XML serialization is (for good and bad) defined explicitly
override def toXML =
<person>
<firstName>{firstName}</firstName>
<surName>{surName}</surName>
<age>{age}</age>
</person>
}
object Person {
// We define the Json Writes in the companion object,
// so it will be automatically inferred whenever we want to write this class
implicit val personWrites = Json.writes[Person]
}
// Pretend this is for real...
object PersonRepository {
def get(id: Int) = Person("Erik", "Fried", 34)
}
GET /person/:id controllers.PersonResource.getPerson(id: Int)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment