Вернуть ответ json с подмножеством свойств объекта в spray-json

У меня есть класс API, вдохновленный демо-версией spray scala здесь Я пишу, что будет отображать человека как объект 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)
        }
      }
    }
  }
}

Проблема в том, что marshal(bob) возвращает JSON следующим образом:

{
  "name": "Bob",
  "firstName": "Parr",
  "age": 32
}

Представьте, что мне нужно отобразить JSON без «возраста» следующим образом:

{
  "name": "Bob",
  "firstName": "Parr"
}

Как это могло быть достигнуто? У меня есть одна мысль: есть ли в Scala способ создать объект, являющийся подмножеством свойств другого объекта? Или, может быть, у spray-json есть какая-то особая поддержка, позволяющая не упорядочивать свойство, которое не следует добавлять в ответ сервера?


person benstpierre    schedule 13.08.2014    source источник


Ответы (1)


Согласно документации по spray-json, вы должны предоставить собственный формат 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)
person Vladimir Petrosyan    schedule 13.08.2014