6

Play Framework 2.1.3 で Ajax POST リクエストを処理しようとしています。投稿データは JSON オブジェクトであり、次のようなツリー構造を持っています。

{ id: "a", name: "myname", kids : [{ id: "a1", name : "kid1", kids: []}, {id: "a2", name: "kid2", kids: [{id: "aa1", name :"grandkid", kids: []}]}]

「子」を任意の深さで入れ子にしたいと思います。私が念頭に置いているクラスは次のようなものです (再帰性が問題になる可能性があることは認識しています)。

case class Person {
  id: String,
  name: String,
  kids: Array[Person]
}

私が念頭に置いているフォーマット:

implicit val personFormat:Format[Person] = Json.format[Person]

私が書いた Format で Play がエラーをスローしています:

型の不一致; 見つかりました: controllers.Resources.Person 必須: 配列[controllers.Resources.Person]

Play が Tree 構造を持っていることは承知しています。それをJSON読み取りに結び付ける方法に関する例/ドキュメントが見つかりませんでした。

どんな助けでも大歓迎です、ありがとう

4

2 に答える 2

10

次のような再帰的な val が必要になります。

implicit val jsonReads: Reads[Person] = ((__ \ "id").read[String] and (__ \ "name").read[String] and (__ \ "kids").read[Seq[Person]])(apply _)

(コレクションの型を Array から Seq に変更しました。より一般的であり、ダウンライン コードに影響を与えずに実装を変更できるからです。)

これは、ここに記載されている構文を使用しています。

于 2013-10-26T19:08:21.160 に答える
2

これが機能していることを確認する唯一の方法は、Person ケース クラスで Array[Person] の代わりに JsArray または Array[String] を使用することです。JSON マクロ インセプションは、プリミティブの読み取り + 書き込みコードと、暗黙的な JSON 読み取り + 書き込みコードが既に存在するオブジェクトのリスト、マップ、および配列のみを生成できます。基本的に、自分自身を参照するケース クラスを持つことはできません。

package models

import play.api.libs.json._

case class Person(
  id   : String,
  name : String,
  kids : JsArray
)

object Person extends ((String,String,JsArray) => Person) {

  implicit val jsonFormat = Json.format[Person]

}
于 2013-10-26T19:01:33.990 に答える