/ / JSON Читає комбінатор в Play scala 2.x не працює для Map [String, _] - json, scala, playframework, playframework-2.0

JSON Читає комбінатор у програмі. Скала 2.x не працює для Map [String, _] - json, scala, playframework, playframework-2.0

У мене є додаток Play-scala v2.3. Дивлячись з це керівництво про Json Combinators, Я намагаюся зробити це:

object Application extends Controller {

case class Foo(id: String, docs: List[Map[String, _]])

implicit val fooReads = (
(JsPath  "id").read[String] and
(JsPath  "docs").read[List[Map[String, _]]]
)(Foo.apply _)

...
}

Але тоді я отримав помилку компіляції:

No Json deserializer found for type List[Map[String, _]]. Try to implement an implicit Reads or Format for this type.
(JsPath  "docs").read[List[Map[String, _]]]
^

Це приклад json, який потрібно прочитати:

{
"id": "001",
"docs": [
{
"name": "Billy",
"level": 2,
"marked": false
},
{
"name": "Fred",
"level": 5,
"marked": true
}
]
}

Я також спробував:

  case class Foo(id: String, docs: Map[String, _])

implicit val fooReads = (
(JsPath  "id").read[String] and
(JsPath  "docs").read[Map[String, _]]
)(Foo.apply _)

Аналогічна помилка.

Здається, комбінатор JSON не працює Map тип. Хто-небудь знає, як вирішити це?

Відповіді:

4 для відповіді № 1

Вам набагато краще уникати Map[String, Any], і Scala і Play роблять це легко. Набагато краще рішення полягає у визначенні спеціального класу випадків для речей, які ви намагаєтеся представити як карту:

import play.api.libs.json._

case class Doc(name: String, level: Int, marked: Boolean)
case class Foo(id: String, docs: List[Doc])

implicit val docFormat = Json.format[Doc]
implicit val fooFormat = Json.format[Foo]

val json = Json.parse(...)

І потім:

scala> json.as[Foo]
res0: Foo = Foo(001,List(Doc(Billy,2,false), Doc(Fred,5,true)))

Або якщо потрібно більше контролю:

import play.api.libs.functional.syntax._
import play.api.libs.json._

implicit val fooReads: Reads[Foo] = (
(__  "id).read[String] and
(__  "docs).read(
Reads.list((
(__  "name).read[String] and
(__  "level).read[Int] and
(__  "marked).read[Boolean]
)(Doc.apply _))
)
)(Foo.apply _)

Якщо вам дійсно потрібно a Map[String, Any], ви завжди можете написати метод перетворення Doc.