7

我正在尝试(但失败)了解 spray-json 如何将 json 馈送转换为对象。如果我有一个简单的键 -> 值 json 提要,那么它似乎工作正常,但我想读取的数据出现在如下列表中:

[{
    "name": "John",
    "age": "30"
},
{
    "name": "Tom",
    "age": "25"
}]

我的代码如下所示:

package jsontest

import spray.json._
import DefaultJsonProtocol._

object JsonFun {

  case class Person(name: String, age: String)
  case class FriendList(items: List[Person])

  object FriendsProtocol extends DefaultJsonProtocol {
    implicit val personFormat = jsonFormat2(Person)
    implicit val friendListFormat = jsonFormat1(FriendList)
  }

  def main(args: Array[String]): Unit = {

    import FriendsProtocol._

    val input = scala.io.Source.fromFile("test.json")("UTF-8").mkString.parseJson

    val friendList = input.convertTo[FriendList]

    println(friendList)
  }

}    

如果我更改我的测试文件,使其只有一个人不在数组中并运行,val friendList = input.convertTo[Person]那么它可以工作并且所有内容都可以解析,但是一旦我尝试解析数组,它就会失败并出现错误Object expected in field 'items'

谁能指出我做错的方向?

4

2 回答 2

9

好吧,在花费数小时试图让某些东西正常工作之后,在向 StackOverflow 发布一些东西后,通常是这样,我已经设法让它工作了。

FriendsProtocol 的正确实现是:

object FriendsProtocol extends DefaultJsonProtocol {
  implicit val personFormat = jsonFormat2(Person)
  implicit object friendListJsonFormat extends RootJsonFormat[FriendList] {
    def read(value: JsValue) = FriendList(value.convertTo[List[Person]])
    def write(f: FriendList) = ???
  } 
}

告诉 Spray 如何读/写(在我的情况下只是读)列表对象足以让它工作。

希望对其他人有所帮助!

于 2015-02-15T19:47:26.983 回答
2

为了使 Friend 数组更易于使用,通过实现适当的 apply 和 length 方法来扩展 IndexedSeq[Person]trait。这将允许直接在 FriendsArray 实例本身上使用标准 Scala 集合 API 方法,如 map、filter 和 sortBy,而无需访问它包装的底层 Array[Person] 值。

case class Person(name: String, age: String)

// this case class allows special sequence trait in FriendArray class
// this will allow you to use .map .filter etc on FriendArray
case class FriendArray(items: Array[Person]) extends IndexedSeq[Person] {
    def apply(index: Int) = items(index)
    def length = items.length
}

object FriendsProtocol extends DefaultJsonProtocol {
  implicit val personFormat = jsonFormat2(Person)
  implicit object friendListJsonFormat extends RootJsonFormat[FriendArray] {
    def read(value: JsValue) = FriendArray(value.convertTo[Array[Person]])
    def write(f: FriendArray) = ???
  } 
}

import FriendsProtocol._

val input = jsonString.parseJson
val friends = input.convertTo[FriendArray]
friends.map(x => println(x.name))
println(friends.length)

这将打印:

John
Tom
2
于 2016-04-06T10:38:15.903 回答