Scala/Play:将JSON解析为Map而不是JsObject [英] Scala/Play: parse JSON into Map instead of JsObject
问题描述
在Play Framework的首页上,他们声称"JSON是一等公民".我还没有看到证明.
On Play Framework's homepage they claim that "JSON is a first class citizen". I have yet to see the proof of that.
在我的项目中,我正在处理一些非常复杂的JSON结构.这只是一个非常简单的示例:
In my project I'm dealing with some pretty complex JSON structures. This is just a very simple example:
{
"key1": {
"subkey1": {
"k1": "value1"
"k2": [
"val1",
"val2"
"val3"
]
}
}
"key2": [
{
"j1": "v1",
"j2": "v2"
},
{
"j1": "x1",
"j2": "x2"
}
]
}
现在,我知道Play正在使用Jackson解析JSON.我在Java项目中使用Jackson,然后会做类似以下的简单事情:
Now I understand that Play is using Jackson for parsing JSON. I use Jackson in my Java projects and I would do something simple like this:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> obj = mapper.readValue(jsonString, Map.class);
这可以很好地将我的JSON解析为Map对象,这就是我想要的-字符串和对象对的Map,并允许我轻松地将数组转换为ArrayList
.
This would nicely parse my JSON into Map object which is what I want - Map of string and object pairs and would allow me easily to cast array to ArrayList
.
Scala/Play中的相同示例如下所示:
The same example in Scala/Play would look like this:
val obj: JsValue = Json.parse(jsonString)
这反而给了我一个专有的JsObject
类型,这并不是我真正想要的
This instead gives me a proprietary JsObject
type which is not really what I'm after.
我的问题是:我可以像在Java中一样轻松地将Scala/Play中的JSON字符串解析为Map
而不是JsObject
吗?
My question is: can I parse JSON string in Scala/Play to Map
instead of JsObject
just as easily as I would do it in Java?
侧面问题:是否有理由在Scala/Play中使用JsObject
代替Map
?
Side question: is there a reason why JsObject
is used instead of Map
in Scala/Play?
我的堆栈:Play Framework 2.2.1/Scala 2.10.3/Java 8 64bit/Ubuntu 13.10 64bit
My stack: Play Framework 2.2.1 / Scala 2.10.3 / Java 8 64bit / Ubuntu 13.10 64bit
更新:我可以看到特拉维斯的答案是正确的,所以我认为这对每个人都有意义,但是我仍然看不到如何将其用于解决我的问题.假设我们有这个示例(jsonString):
UPDATE: I can see that Travis' answer is upvoted, so I guess it makes sense to everybody, but I still fail to see how that can be applied to solve my problem. Say we have this example (jsonString):
[
{
"key1": "v1",
"key2": "v2"
},
{
"key1": "x1",
"key2": "x2"
}
]
好吧,根据所有指示,我现在应该放所有我不了解其目的的样板:
Well, according to all the directions, I now should put in all that boilerplate that I otherwise don't understand the purpose of:
case class MyJson(key1: String, key2: String)
implicit val MyJsonReads = Json.reads[MyJson]
val result = Json.parse(jsonString).as[List[MyJson]]
看起来不错,是吗?但是等一下,数组中又出现了另一个元素,这完全破坏了这种方法:
Looks good to go, huh? But wait a minute, there comes another element into the array which totally ruins this approach:
[
{
"key1": "v1",
"key2": "v2"
},
{
"key1": "x1",
"key2": "x2"
},
{
"key1": "y1",
"key2": {
"subkey1": "subval1",
"subkey2": "subval2"
}
}
]
第三个元素不再与我定义的案例类匹配-我再次处于平方.我每天都能在Java中使用这样复杂得多的JSON结构,Scala是否建议我简化JSON以适应其类型安全"策略?如果我错了,请纠正我,但是我虽然应该用这种语言来提供数据,而不是相反?
The third element no longer matches my defined case class - I'm at square one again. I am able to use such and much more complicated JSON structures in Java everyday, does Scala suggest that I should simplify my JSONs in order to fit it's "type safe" policy? Correct me if I'm wrong, but I though that language should serve the data, not the other way around?
UPDATE2:解决方案是将Jackson模块用于scala(我的答案中的示例).
UPDATE2: Solution is to use Jackson module for scala (example in my answer).
推荐答案
我选择将 Jackson模块用于scala .
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
val obj = mapper.readValue[Map[String, Object]](jsonString)
这篇关于Scala/Play:将JSON解析为Map而不是JsObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!