3

我正在使用 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]]
}
4

2 回答 2

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]未提供 for 的格式,因为 json api 将解析为隐式和通用的Readsand OWrites

最后,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的读取是安全的。FBUservalidatemaprecoverTotal

一些单词

关于安全性的最后一点说明Json.parse是不安全的,因此为了更加安全,您应该根据工作流程考虑一些选项,其中一些是: * 使用 json 正文解析器,它可以让您显式处理错误的 json 格式 * 使用在控制器中为这种特殊情况定义的专用案例类(然后使用类似 for 的 inception 定义它的 Reads/... FBUser

于 2013-04-28T14:47:54.957 回答
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
于 2013-04-26T15:24:24.863 回答