我正在尝试在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)
使用此Play
Framework页面上的“提示”将Scala转换为Json时,我发现了以下内容(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]过滤给出警告,但似乎给出了我想要的答案。如果可以应用这两个过滤器,然后对结果的值使用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)
Play 2.1 JSON API没有为Type提供序列化器Map[String, Ojbect]
。
为特定类型定义case class
和Format
,而不是Map[String, Object]
:
// { "val1" : "xxx", "val2" : ["a", "b", "c"] }
case class Hoge(val1: String, val2: List[String])
implicit val hogeFormat = Json.format[Hoge]
如果您不想创建案例类。以下代码为Map [String,Object]提供JSON序列化器/反序列化器:
implicit val objectMapFormat = new Format[Map[String, Object]] {
def writes(map: Map[String, Object]): JsValue =
Json.obj(
"val1" -> map("val1").asInstanceOf[String],
"val2" -> map("val2").asInstanceOf[List[String]]
)
def reads(jv: JsValue): JsResult[Map[String, Object]] =
JsSuccess(Map("val1" -> (jv \ "val1").as[String], "val2" -> (jv \ "val2").as[List[String]]))
}
import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.json.Json.JsValueWrapper
implicit val objectMapFormat = new Format[Map[String, Object]] {
def writes(map: Map[String, Object]): JsValue =
Json.obj(map.map{case (s, o) =>
val ret:(String, JsValueWrapper) = o match {
case _:String => s -> JsString(o.asInstanceOf[String])
case _ => s -> JsArray(o.asInstanceOf[List[String]].map(JsString(_)))
}
ret
}.toSeq:_*)
def reads(jv: JsValue): JsResult[Map[String, Object]] =
JsSuccess(jv.as[Map[String, JsValue]].map{case (k, v) =>
k -> (v match {
case s:JsString => s.as[String]
case l => l.as[List[String]]
})
})
}
样例代码:
val jv = Json.toJson(Map("val1" -> "xxx", "val2" -> List("a", "b", "c"), "val3" -> "sss", "val4" -> List("d", "e", "f")))
println(jv)
val jr = Json.fromJson[Map[String, Object]](jv)
println(jr.get)
输出:
> {"val1":"xxx","val2":["a","b","c"],"val3":"sss","val4":["d","e","f"]}
> Map(val1 -> xxx, val2 -> List(a, b, c), val3 -> sss, val4 -> List(d, e, f))
有人能分享一下如何将转换为吗?
在我的项目中,我有一个Akka层,它返回一个,接收Future的部分是Java风格。 团队中的人不了解Scala,他们宁愿使用,因为他们更了解Java 8 API。 有没有什么好方法可以将一个转换成一个?。 显然是以非阻塞的方式。 当做
问题内容: 有一种简单的方法可以将给定的Row对象转换为json吗? 但是我只想将一个Row转换为json。这是我要尝试执行的伪代码。 更准确地说,我正在读取json作为Dataframe中的输入。我正在产生主要基于列的新输出,但对于所有不适合列的信息都具有一个json字段。 我的问题是编写此函数的最简单方法是什么:convertRowToJson() Psidom解决方案: 仅当行只有一个级别而
RDD是以数组[数组[字符串]的格式创建的,具有以下值: 我想用模式创建一个数据帧: 接下来的步骤: 给出以下错误:
问题内容: 我目前正在开发一个Scala应用程序,该应用程序利用Spring-Boot和Swagger发送和接收REST调用。 Swagger和Spring-Boot是纯Java项目,与Scala的兼容性有限,但是我似乎找到了解决该问题的方法。 由于Spring- Boot和Swagger将请求作为Java对象处理(需要使用setter和getter才能工作),因此我必须将请求视为Java对象,然
我有一些scala代码是我用IntelliJ和SBT-Plugin编写的,希望提供给我作为C++的DLL的代码。 我已经尝试过使用'ikvmc':我通过'package'将所有类打包在一个jar中。之后,我手动设置了一个jar,其中包含我使用的所有依赖项(scala-library、scama、jamtio、jama)。不幸的是,我得到了很多警告:'IKVMC0119'、“Emitted java