【问题标题】:Providing a JsonFormat for a Sequence of Objects为对象序列提供 JsonFormat
【发布时间】:2014-03-12 11:37:51
【问题描述】:

我试图在这里找到一些帮助来应用 DefaultJsonProtocol 的 JsonFormat 扩展 到一个包含对象序列的类。

所以对于课程:

class Person(val name: String, [......], val adresses: Seq[Adress])
class Adress(val streetname: String, val plz: BigDecimal, val city: String)

现在我想应用我的 JsonFormat:

object PersonJsonProtocol extends DefaultJsonProtocol {
  implicit object PersonJsonFormat extends RootJsonFormat[Person] {
    def write(pers: Person) = JsObject(
    "name" -> JsString(pers.name),
    [......],
    "adresses" -> JsArray(pers.adresses)
)
def read(value: JsValue) = {...}
}

但实际上我不知道该怎么做。 我搜索了 spray-json 文档并通过 google、stackoverflow & Co. 我对 Scala/Spray 完全陌生,也许我只是错过了重点。所以,也许这里有人好心帮助我。没有地址序列我会工作。

使用示例中提供的 JsArray,我得到类型不匹配。它正在检查一个 List[JsValue] 但也与转换为列表不匹配仍然存在。

我还尝试插入一个单独的 AdressJsonProtocol 并通过以下方式包含它: "addresses" -> AdressJsonFormat.write(pers.adresses) 但它又是一个序列......

【问题讨论】:

    标签: json scala spray spray-json


    【解决方案1】:

    您不需要为每个案例类编写 DefaultJsonProtocol,除非您需要一些特殊的逻辑(格式化、过滤...)

    您是否尝试过简单地使用默认案例类序列化?

    implicit val formatPerson = jsonFormat6(Adress)
    implicit val formatAddress = jsonFormat3(Adress)
    

    jsonFormat'number'中的数字代表你的case类的成员数。

    然后 spray-json 将在序列化 Person 时处理嵌套的 Address 集合。

    【讨论】:

    • 谢谢,我相信这也可以,但我想使用 DefaultJsonProtocol 直接访问 Json 名称和提供的值,并与原始类分开。我应该在原帖中说明这一点。抱歉,我想投票支持您的答案,但我还没有足够的声誉。但也谢谢你!
    • @Klink,你说:“我想使用 DefaultJsonProtocol 直接访问 Json 名称和提供的值并与原始类分开”是什么意思?
    • @DaveSwartz 很抱歉再次不清楚。所以我的意思是 DefaultJsonProtocol 的扩展允许我处理生成的 Json 中提供的信息。例如: "name" -> JsString(pers.name) 也可以是 "name" -> JsString(pers.name+", "+pers.title) 或 "person-name" -> JsString(pers.name)
    • 在查看您的答案时,我意识到我在代码中的“jsonFormat”之后使用了错误的数字。
    【解决方案2】:

    spray.json.CollectionFormats的出处。

    这是一个可运行的实现:

    import spray.json._
    
    class Adress(val streetname: String, val plz: BigDecimal, val city: String)
    
    class Person(val name: String, val adresses: Seq[Adress])
    
    object PersonJsonProtocol extends DefaultJsonProtocol {
      implicit object AdressJsonFormat extends RootJsonFormat[Adress] {
        def write(addr: Adress) = JsObject(Map(
          "streetname" -> JsString(addr.streetname),
          "plz" -> JsNumber(addr.plz),
          "city" -> JsString(addr.city)
        ))
        def read(value: JsValue): Adress = ???
      }
      implicit object PersonJsonFormat extends RootJsonFormat[Person] {
        def write(pers: Person) = JsObject(Map(
          "name" -> JsString(pers.name),
          "adresses" -> JsArray(pers.adresses.map(_.toJson).toList)
        ))
        def read(value: JsValue): Person = ???
      }
    }
    
    object Main extends App {
      import PersonJsonProtocol._
      val person = new Person("joe", Seq(new Adress("street", 123, "city")))
      println("poso's default toString: %s".format(person))
      val personJVal = person.toJson
      println("JValue's toString: %s".format(personJVal))
      val personJson = personJVal.prettyPrint
      println("pretty-printing: %s".format(personJson))
    }
    

    产生:

    poso's default toString: Person@680ccad
    JValue's toString: {"name":"joe","adresses":[{"streetname":"street","plz":123,"city":"city"}]}
    pretty-printing: {
      "name": "joe",
      "adresses": [{
        "streetname": "street",
        "plz": 123,
        "city": "city"
      }]
    }
    

    【讨论】:

    • 感谢“spray.json.CollectionFormats”和 JsArray(pers.adresses.map(_.toJson).toList) 的提示!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 2022-01-03
    • 2020-04-20
    • 1970-01-01
    • 2021-10-14
    相关资源
    最近更新 更多