Returning json response with subset of object properties in aerosol
I have an API class inspired by the scala demo spray here I am writing that will make a person as a JSON object in a spray route.
trait UsersApi {
case class Person(name: String, firstName: String, age: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val PersonFormat = jsonFormat3(Person)
}
import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._
import spray.util._
val bob = Person("Bob", "Parr", 32)
val usersApiRouting: Route = {
path("users") {
get {
complete {
marshal(bob)
}
}
}
}
}
The problem is that marshal (bob) returns JSON like this:
{
"name": "Bob",
"firstName": "Parr",
"age": 32
}
Imagine I need to render JSON without "age" like this:
{
"name": "Bob",
"firstName": "Parr"
}
How can this be achieved? One thought I have, is there a scala way to make an object that is a subset of the properties of another object? Or maybe the atomizer has some support for not sorting a property that shouldn't be added to the server's response?
+3
source to share
1 answer
According to spray-json docs , you should provide a custom jsonFormat like this:
case class Person(name: String, firstName: String, age: Option[Int])
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object PersonFormat extends RootJsonFormat[Person] {
def write(p: Person) =JsObject(
"name" -> JsString(p.name),
"firstName" -> JsString(p.firstName)
)
def read(value: JsValue) = {
value.asJsObject.getFields("name", "firstName", "age") match {
case Seq(JsString(name), JsString(firstName), JsNumber(age)) =>
new Person(name, firstName, Some(age.toInt))
case Seq(JsString(name), JsString(firstName)) =>
new Person(name, firstName, None)
case _ => throw new DeserializationException("Person expected: " + value.asJsObject.getFields("name", "firstName", "age").toString)
}
}
}
}
import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._
import spray.util._
val bob = Person("Bob", "Parr", Some(32))
val bobJson = bob.toJson.toString //bobJson: String = {"name":"Bob","firstName":"Parr"}
val bobObj = bobJson.parseJson.convertTo[Person] //bobObj: Person = Person(Bob,Parr,None)
+9
source to share