Json 如何在Scala中获取JsArray的5个元素?

Json 如何在Scala中获取JsArray的5个元素?,json,scala,Json,Scala,下面的代码已编译,但引发了一个错误:线程“main”scala.MatchError中的异常:[{“id”:6430758,“name”:…](类play.api.libs.json.JsArray)。如何通过获取项和其中的列表以及仅5个元素来读取给定链接的json import play.api.libs.json._ def getProjects: List[Map[String, Any]] = { val iter = getJSON("https://api.githu

下面的代码已编译,但引发了一个错误:
线程“main”scala.MatchError中的异常:[{“id”:6430758,“name”:…](类play.api.libs.json.JsArray)
。如何通过获取
项和其中的
列表以及仅5个元素来读取给定链接的json

import play.api.libs.json._

  def getProjects: List[Map[String, Any]] = {
    val iter = getJSON("https://api.github.com/search/repositories?q=scala")
    val json: JsValue = Json.parse(iter.get mkString "\n")
    val projects = (json \ "items") match {
      case l: List[Map[String, Any]] => l take 5
    }
    projects
  }

  def getJSON(url: String): Try[Iterator[String]] =
    Try(Source.fromURL(url).getLines) recover {
      case e: FileNotFoundException =>
        throw new AppException(s"Requested page does not exist: ${e.getMessage}.")
      case e: MalformedURLException =>
        throw new AppException(s"Please make sure to enter a valid URL: ${e.getMessage}.")
      case _ => throw new AppException("An unexpected error has occurred.")
    }

因为您使用的是Play,所以您应该在它的
JsValue
抽象中工作,而不是跳转到
Map[String,Any]

匹配失败的原因是
json\“items”
不是
Map[String,Any]
,而是
JsValue
。理想情况下,您知道json的结构(项目的架构是什么)并且可以反序列化为:

case class Project(id: Long, name: String, ...)

object Project {
  implicit val fmt = Json.format[Project]
}

val projects = WS.get("https://api.github.com/search/repositories?q=scala").map { response =>
  response.json.validate[Map[String, Project]].map(_ take 5)
}

这就给您留下了一个
Future[JsResult[Map[String,Project]]]
。外部类型是
Future
,因为操作本质上是异步的,
JsResult
将是一个
JsSuccess
与您的
Map[String,Project]
或一个
JsError
包含原因无法验证您的JSON。

因为您使用的是Play,所以您应该在其
JsValue
抽象中工作,而不是跳出到
映射[字符串,任意]

匹配失败的原因是
json\“items”
不是
Map[String,Any]
,而是
JsValue
。理想情况下,您知道json的结构(项目的架构是什么)并且可以反序列化为:

case class Project(id: Long, name: String, ...)

object Project {
  implicit val fmt = Json.format[Project]
}

val projects = WS.get("https://api.github.com/search/repositories?q=scala").map { response =>
  response.json.validate[Map[String, Project]].map(_ take 5)
}

这就给您留下了一个
Future[JsResult[Map[String,Project]]]
。外部类型是
Future
,因为操作本质上是异步的,
JsResult
将是一个
JsSuccess
与您的
Map[String,Project]
或一个
JsError
包含原因无法验证您的JSON。

它感觉又快又脏,但如果这确实是您想要做的,那么您可以尝试:

val listOfMaps: Seq[Map[String, String]] =
    (res1 \ "items").as[JsArray].value.map { jsobj =>
        jsobj.as[JsObject].value.map { case (key, value) =>
            key -> value.toString
        }
    }.take(5)

更好的选择是创建一个case类,其中包含您期望的键和类型,并编写一个Reads来解析该case类的Json。请参阅。然后,您将有一个case类列表,可以很容易地从中获取5个。这感觉既快又脏,但如果这确实是您想要做的,那么您可以尝试:

val listOfMaps: Seq[Map[String, String]] =
    (res1 \ "items").as[JsArray].value.map { jsobj =>
        jsobj.as[JsObject].value.map { case (key, value) =>
            key -> value.toString
        }
    }.take(5)

更好的选择是创建一个case类,其中包含您期望的键和类型,并编写一个Reads来将Json解析到该case类。请参阅。然后您将有一个case类列表,您可以从中轻松获取5个。

类型为
(Json\“items”)
JsArray@ipoteka这是JsValue,不是JsArray。@Ryan他可以轻松地与JsArray而不是List进行匹配。
(json\“items”)
的类型是JsArray@ipoteka这是JsValue,不是JsArray。@Ryan他可以轻松地与JsArray而不是List进行匹配。