2015-03-09 1 views
2

У меня есть приложение Play-Scala v2.3. Глядя из this guide about Json Combinators, я пытаюсь сделать это:JSON Читает комбинатор в Play scala 2.x не работает для карты [String, _]

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 для Play Play не работает для Map type. Кто-нибудь знает, как это решить?

+0

Он может работать для типа «Карта», но не 'Map [String, _]'. '_' является нетипизированным, поэтому он не знает, что с ним делать. Почему вы пытаетесь использовать «Map [String, _]» в первую очередь? –

+0

@mz: Я читал из [здесь] (https://www.playframework.com/documentation/2.3.x/ScalaJsonInception), он сказал, что 'Json Macros, как известно, принимают Option/Seq/List/Set & Map [String , _] ', может быть, это намек на то, что он должен работать (в прошлом?). Причина использования Карты, потому что у меня есть метод службы, который принимает параметр «Список [Карта [String, _]]», хотя я могу использовать список классов case для документов, но затем мне нужно преобразовать его в List [Map [String, _]]. – null

+0

Я не думаю, что это означает буквально сказать «Карта [String, _]', но «Map [String, Int]», «Map [String, String]» и т. Д. Для типов, которые имеют смысл. –

ответ

4

Вам будет намного лучше избегать 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 _) 

Если вам действительно нужен Map[String, Any], вы всегда можете написать способ преобразования на Doc.