2.1RC Play フレームワークで Scala を JSON に変換しようとしています。
次のようにして JSON を取得できます。
import play.api.libs.json._
val a1=Map("val1"->"a", "val2"->"b")
Json.toJSon(a1)
a1 は Map[String,String] であり、正常に機能するためです。
しかし、Map[String,Object] のようにもっと複雑なものがある場合、それは機能しません。
val a = Map("val1" -> "xxx", "val2"-> List("a", "b", "c"))
Json.toJSon(a1)
>>> error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]
次のようなことができることがわかりました。
val a2 = Map("val1" -> Json.toJson("a"), "val2" -> Json.toJson(List("a", "b", "c")))
Json.toJson(a2)
そして、それは機能します。
しかし、どうすれば一般的な方法でそれを行うことができますか? 私は次のようなことができると思いました:
a.map{ case(k,v)=> (k, Json.toJson(v) )}
>>> error: No Json deserializer found for type Object
しかし、それでもデシリアライズできないというエラーが表示されます
追加情報:
Json.toJson は Map[String, String] を JsValue に変換できます。
scala> val b = Map( "1" -> "A", "2" -> "B", "3" -> "C", "4" -> "D" )
b: scala.collection.immutable.Map[String,String] = Map(1 -> A, 2 -> B, 3 -> C, 4 -> D)
scala> Json.toJson(b)
res31: play.api.libs.json.JsValue = {"1":"A","2":"B","3":"C","4":"D"}
しかし、Map[String, Object] を変換しようとすると失敗します。
scala> a
res34: scala.collection.immutable.Map[String,Object] = Map(val1 -> xxx, val2 -> List(a, b, c))
scala> Json.toJson(a)
<console>:12: error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]. Try to implement an implicit Writes or Format for this type.
Json.toJson(a)
Scala から Json への変換に関するこの Play Framework ページの「ヒント」を使用すると、次のことがわかりました ( http://www.playframework.org/documentation/2.0.1/ScalaJson )。
Map[String, Object] の代わりに Map[String, JsValue] がある場合、Json.toJson() は機能します。
scala> val c = Map("aa" -> Json.toJson("xxxx"), "bb" -> Json.toJson( List("11", "22", "33") ) )
c: scala.collection.immutable.Map[String,play.api.libs.json.JsValue] = Map(aa -> "xxxx", bb -> ["11","22","33"])
scala> Json.toJson(c)
res36: play.api.libs.json.JsValue = {"aa":"xxxx","bb":["11","22","33"]}
だから、私が望むのは、Map[String, Object] が与えられた場合、Object の値がすべて元々 String または List[String] 型であることがわかっている場合、関数 Json.toJson() をすべてに適用する方法です。マップ内の値を取得し、Map[String, JsValue] を取得します。
また、純粋に文字列である値と List[String] 型 (だった) の値を除外できることもわかりました。
scala> val a1 = a.filter({case(k,v) => v.isInstanceOf[String]})
a1: scala.collection.immutable.Map[String,Object] = Map(val1 -> xxx)
scala> val a2 = a.filter({case(k,v) => v.isInstanceOf[List[String]]})
<console>:11: warning: non-variable type argument String in type List[String] is unchecked since it is eliminated by erasure
val a2 = a.filter({case(k,v) => v.isInstanceOf[List[String]]})
^
a2: scala.collection.immutable.Map[String,Object] = Map(val2 -> List(a, b, c))
List[String] フィルタリングは警告を出しますが、私が望む答えを与えるようです。2 つのフィルターを適用してから、結果の値に対して Json.toJson() を使用し、結果を組み合わせることができれば、うまくいくでしょうか?
しかし、フィルタリングされた結果は依然として Map[String, Object] 型であり、問題を引き起こします。
scala> Json.toJson(a1)
<console>:13: error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]. Try to implement an implicit Writes or Format for this type.
Json.toJson(a1)