Scala中的JSON到XML以及处理Option()结果
从Scala解释器中考虑以下内容:Scala中的JSON到XML以及处理Option()结果,scala,scala-option,Scala,Scala Option,从Scala解释器中考虑以下内容: scala> JSON.parseFull("""{"name":"jack","greeting":"hello world"}""") res6: Option[Any] = Some(Map(name -> jack, greeting -> hello world)) 为什么地图会以()形式返回?我如何使用它 我想将这些值放在xml模板中: <test> <name>name goes here</
scala> JSON.parseFull("""{"name":"jack","greeting":"hello world"}""")
res6: Option[Any] = Some(Map(name -> jack, greeting -> hello world))
为什么地图会以()形式返回?我如何使用它
我想将这些值放在xml模板中:
<test>
<name>name goes here</name>
<greeting>greeting goes here</greeting>
</test>
名字就在这里
问候语就在这里
什么是Scala从某些(东西)中获取映射并在xml中获取这些值的方法?
parseFull
返回一个选项
,因为字符串可能不是有效的JSON(在这种情况下,它将返回None
,而不是Some
)
从Some
中获取值的常用方法是对其进行模式匹配,如下所示:
result match {
case Some(map) =>
doSomethingWith(map)
case None =>
handleTheError()
}
res6 collect { case x: Map[String, String] => renderXml(x) }
如果您确定输入总是有效的,因此不需要处理无效输入的情况,则可以使用
选项
上的get
方法,当调用None
时,该方法将引发异常。您可能应该使用类似以下内容:
result match {
case Some(map) =>
doSomethingWith(map)
case None =>
handleTheError()
}
res6 collect { case x: Map[String, String] => renderXml(x) }
其中:
def renderXml(m: Map[String, String]) =
<test><name>{m.get("name") getOrElse ""}</name></test>
两者都是等价的。当您有可选值时,应使用map
、flatMap
、filter
、collect
等转换程序中的选项,避免通过模式匹配或get
方法提取选项的内容。你永远不应该使用选项。获取-这是你做错了的典型标志。应该避免模式匹配,因为它代表了程序中的一个分支,因此增加了圈复杂度——您唯一希望这样做的时候可能是为了性能
实际上,您有一个问题,parseJSON
方法的结果是一个选项[Any]
(原因是它是一个选项
,大概是解析可能不会成功,选项
是一种比null
更优雅的处理null的方法)
但是我上面代码的问题是,由于类型擦除,无法在运行时检查案例x:Map[String,String]
(即scala可以检查选项是否包含映射
,但不能检查映射
的类型参数是否都是字符串
。该代码将向您发出未选中的警告。返回选项
,因为parseFull
根据输入具有不同的可能返回值,或者可能无法解析输入(给出None
)。因此,除了将键与值关联的可选Map
,如果JSON字符串表示数组,还可以返回可选的列表
例如:
scala> import scala.util.parsing.json.JSON._
import scala.util.parsing.json.JSON._
scala> parseFull("""{"name":"jack"}""")
res4: Option[Any] = Some(Map(name -> jack))
scala> parseFull("""[ 100, 200, 300 ]""")
res6: Option[Any] = Some(List(100.0, 200.0, 300.0))
您可能需要进行模式匹配以实现所需,例如:
scala> parseFull("""{"name":"jack","greeting":"hello world"}""") match {
| case Some(m) => Console println ("Got a map: " + m)
| case _ =>
| }
Got a map: Map(name -> jack, greeting -> hello world)
现在,如果您想生成XML输出,可以使用上面的方法迭代键/值对:
import scala.xml.XML
parseFull("""{"name":"jack","greeting":"hello world"}""") match {
case Some(m: Map[_,_]) =>
<test>
{
m map { case (k,v) =>
XML.loadString("<%s>%s</%s>".format(k,v,k))
}
}
</test>
case _ =>
}
import scala.xml.xml
parseFull(“{”name:“jack”,“greeting:“hello world”}”“)匹配{
案例部分(m:Map[,])=>
{
m map{case(k,v)=>
加载字符串(“%s.”格式(k,v,k))
}
}
案例=>
}
您有两个不同的问题
它被键入为Any
您的数据位于选项
和地图
中
假设我们有数据:
val x: Option[Any] = Some(Map("name" -> "jack", "greeting" -> "hi"))
假设我们想要返回适当的XML(如果有要返回的内容),但不能返回其他内容。然后我们可以使用collect
来收集我们知道如何处理的部分:
val y = x collect {
case m: Map[_,_] => m collect {
case (key: String, value: String) => key -> value
}
}
(注意我们如何将映射中的每个条目分开,以确保它将一个字符串映射到一个字符串——否则我们将不知道如何继续。我们得到:
y: Option[scala.collection.immutable.Map[String,String]] =
Some(Map(name -> jack, greeting -> hi))
好的,那就更好了!现在,如果您知道要在XML中包含哪些字段,您可以请求它们:
val z = for (m <- y; name <- m.get("name"); greet <- m.get("greeting")) yield {
<test><name>{name}</name><greeting>{greet}</greeting></test>
}
这又产生了
z: Option[scala.xml.Elem] =
Some(<test><name>jack</name><greeting>hi</greeting></test>)
z:Option[scala.xml.Elem]=
一些(杰基)
(您可以使用get
来获取选项的内容
,但如果选项
为空(即无
),则会引发异常。)应选择选项上的模式匹配avoided@oxbow_lakes-除非你想在内容上也进行匹配,否则选项上的模式匹配通常是笨拙的。+1我赞同这个答案,并衷心反对“应该避免”和“笨拙”语句。模式匹配是解决此问题最简单、最清晰的方法。感谢所有伟大的答案。对于是否使用模式匹配,似乎存在不同的意见。不知道这是否是最纯粹的战争,但我也将用我忠实的“Scala书中的编程”;-)
z: Option[scala.xml.Elem] =
Some(<test><name>jack</name><greeting>hi</greeting></test>)