我有一个灵感来自spala scala demo here的API类,我写的是在喷射路径中将Person渲染为JSON对象。
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)
}
}
}
}
}
问题是编组(bob)像这样返回JSON:
{
"name": "Bob",
"firstName": "Parr",
"age": 32
}
想象一下,我需要像这样渲染没有“年龄”的JSON:
{
"name": "Bob",
"firstName": "Parr"
}
如何实现这一目标?我有一个想法是Scala有办法使一个对象成为另一个对象属性的子集吗?或者也许喷-json有一些特定的支持,不编组不应该添加到服务器响应的属性?
答案 0 :(得分:9)
根据spray-json docs,你应该像这样提供自定义的jsonFormat:
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)