使用Play 2.1.1迭代JSON中的数组

时间:2013-04-26 14:54:33

标签: json scala playframework playframework-2.0 playframework-json

我正在使用play 2.1.1并且我在迭代数组时遇到问题。我曾在某处读过你可以为List [Object]创建一个读取,但是每当我尝试这样做时,我都会收到错误"No unapply function found"的行

implicit val userListReads: Reads[List[FBUser]] = Json.reads[List[FBUser]]". The issue is " = Json.reads[List[FBUser]]

我无法尝试其他什么。非常感谢任何帮助。

def linkUsers() = Action { implicit request =>
  val json = Json.parse("{\"data\": [{\"name\": \"Me Lazyan\",\"id\": \"1182\"},{\"name\": \"Chales Dselle\",\"id\": \"10115\"},{\"name\": \"Be My\",\"id\": \"10275\"},{\"name\": \"De Rwani\", \"id\": \"11189\"},{\"name\": \"Phoe Johon\", \"id\": \"11372\"}]}")

  val peoples = json.validate[List[FBUser]].get
  peoples.foreach(println)

  Ok(json).withHeaders(CONTENT_TYPE -> "text/json")
}

case class FBUser(
  name: String,
  id: String 
)

object FBUser {
    /** Uses a Scala Macro to define the Reads function */
    implicit val userReads: Reads[FBUser] = Json.reads[FBUser]
    implicit val userListReads: Reads[List[FBUser]] = Json.reads[List[FBUser]]
}

2 个答案:

答案 0 :(得分:13)

目的

即使@ martin的回答是关于json消息与预期结果之间不匹配的直接解决方案,我也想给你一些建议,以便找到一个干净的方法来实现你的目标。

那是因为,AFAICK,你正在重新定义太多的东西,你可以遇到没有报告错误的情况......但只是被NoSuchElementException等不同的错误隐藏。

最后,我想提供一个解决方案,让你的信息保持不变(就像第二个@Martin的解决方案一样)。

命题

我们的想法是将事务打包,并将代码分为三个不同的文件:

FBUser.scala简单地声明了模型结构

package models

case class FBUser(
    name: String,
    id: String
)

formats.scala这是一个收集所有格式定义的包,特别是json:

package models

import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.json.util._
import play.api.libs.json.Json._
import play.api.libs.functional.syntax._

package formats {

  object jsons {
    implicit val fbUserFormat:Format[FBUser] = Json.format[FBUser]
  }

}

请注意,未提供List[FBUser]的格式,因为json api将解析为隐式ReadsOWrites

最后,Application.scala将包含仅与某些用例相关的代码,例如包含data字段的json对象,FBUser列表。

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.json._
import play.api.libs.json.Json._

import models._

object Application extends Controller {

  import models.formats.jsons._
  val readUserFromInput = (__ \ 'data).read[List[FBUser]]

  def index = Action {
    val jsonString = "{\"data\": [{\"name\": \"Me Lazyan\",\"id\": \"1182\"},{\"name\": \"Chales Dselle\",\"id\": \"10115\"},{\"name\": \"Be My\",\"id\": \"10275\"},{\"name\": \"De Rwani\", \"id\": \"11189\"},{\"name\": \"Phoe Johon\", \"id\": \"11372\"}]}"

    val json = Json.parse(jsonString)
    val users = json.validate(readUserFromInput)

    users.map(
      list => Ok(Json.toJson(list)) // or Ok(json) to match exactly you example
    ).recoverTotal{
      err => BadRequest(JsError.toFlatJson(err))
    }
  }

}

在此控制器中,我们可以看到它为初始案例定义了特定的Reads,因此,由于使用{FBUser实例,对数据字段和validate实例的读取的访问是安全的{1}},maprecoverTotal

有些话

关于安全的最后一点,Json.parse是不安全的,所以为了更加安全,你应该考虑一些选项,具体取决于你的工作流程,其中一些是: *使用json body解析器,它可以让你明确地处理坏的json格式 *使用控制器中为此特定情况定义的专用案例类(然后使用像FBUser这样的初始定义其读取/ ...)

答案 1 :(得分:12)

您的json值是一个包含数组的字段data的对象。您正在尝试将单个对象解析为数组。您可能需要将json更改为。

val json = Json.parse("[{\"name\": \"Me Lazyan\",\"id\": \"1182\"},{\"name\": \"Chales Dselle\",\"id\": \"10115\"},{\"name\": \"Be My\",\"id\": \"10275\"},{\"name\": \"De Rwani\", \"id\": \"11189\"},{\"name\": \"Phoe Johon\", \"id\": \"11372\"}]")

或将您的代码更改为

val people = (json \ "data").validate[List[FBUser]].get