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メッセージと期待される結果との不一致に関する直接的な解決策を提供している場合でも、目標を達成するためのクリーンな方法についていくつかアドバイスをしたいと思います.

これは、私の知る限り、あまりにも多くのことを再定義しているためであり、エラーが報告されないケースに遭遇する可能性があります...しかし、NoSuchElementException のような別のエラーによって隠されているだけです。

最後に、メッセージが変更されない解決策を提供したいと思います(2番目の @Martin の解決策のように)。

命題

アイデアは、物事を責任を持ってパッケージ化しておくことであり、コードは3つの異なるファイルに分割されています。

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 は暗黙的で一般的なReadsandに解決されるため、 の形式は提供されないことに注意してくださいOWrites

そして最後に、フィールドApplication.scalaを含む json オブジェクトのような、一部のユース ケースにのみ関連するコードを含む.dataFBUser

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の使用により安全です。validatemaprecoverTotal

いくつかの言葉

安全性に関する最後の注意は安全でJson.parseはないため、さらに安全にするために、ワークフローに応じていくつかのオプションを検討する必要があります。そのうちのいくつかは次のとおりです。この特定のケースのコントローラーで定義された専用のケース クラス (そして、 for のような開始を使用してその 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 に答える