Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中的JSON到XML以及处理Option()结果_Scala_Scala Option - Fatal编程技术网

Scala中的JSON到XML以及处理Option()结果

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解释器中考虑以下内容:

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>)