我一直在与Scala中解析JSON字符串的功能方式的概念作斗争,并且在返回选项(某物)的情况下平放到墙上。我popped the question和有用的答案流入。
问题是,作为Scala的新手,有什么正确的方法?
目前我正在这样做:
import util.parsing.json.JSON._
object JsonSoap {
def main(args: Array[String]) {
val x = parseFull("""{"name":"Joe","surname":"SOAP"}""")
val y = x collect {
case m: Map[_, _] => m collect {
case (key: String, value: String) => key -> value
}
}
val z = for (m <- y; name <- m.get("name"); surname <- m.get("surname"))
yield {
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Person>
<Name>{name}</Name>
<Surname>{surname}</Surname>
</Person>
</soap:Body>
</soap:Envelope>
}
println(z)
}
}
我仍然坚持使用Some()
解决我的问题有一个很好的模式吗?当然,这必须是一个很好的探索领域。如何改进我的代码?
答案 0 :(得分:35)
您不会被Some
“卡住” - 您拥有优势,您拥有Some
!在Java中,你会遇到一个类型没有表达它实际上可能不存在的值的值!
MyThing recklessly = apiCall.getMeAThing();
recklessly.iSureHopeImNotNull(); //OH NOES!
将其与此
进行比较apiCall.getMeAThing foreach (_.cannotPossiblyBeNull)
Option
数据类型意味着查询的“可能不存在”位实际上被烘焙到查询的返回类型中。请坚持使用Option
- 几个星期后,当你去编写Java代码时,你会拔出你的头发并且它不在那里!
你可能会说:
噢,但是我需要拿走我拥有的值并将其加1
我说:
apiCall.getMeAThing map (_ + 1)
您可能会说
噢,但是我需要将它传递给一个方法,如果我有空则默认为空字符串
我说:
foo( apiCall.getMeAThing getOrElse "" )
您可能会说
噢,但我用这个值来调用另一个API方法并获得其他东西
我说:
apiCall.getMeAThing flatMap apiCall.getMeAnotherThing
你肯定会说
噢,但是对于所有这些对象创作来说效率非常低
我说:“试试看,它会很好”
答案 1 :(得分:9)
通常,当您将结果包装在选项中时,您希望使用match
或其中一种monadic方法map
,flatMap
或foreach
。例如,在您的情况下,我们可以做任何这些
val output = z match {
case Some(xml) => xml
case None => "Invalid JSON"
}
println(output)
//or
z.foreach{println} //won't print anything if z is None
//or
println(z.getOrElse("Invalid JSON"))
在大多数情况下,你应该避免这样的事情:
if (z == None) {
println("Invalid")
} else {
println(Z.get)
}
答案 2 :(得分:4)
事情就是:您可能没有得到预期的数据,在这种情况下,无法计算z
。因此,您问题的答案实际上取决于您的对一个问题的回答:当您无法计算z
时,您会做什么?
例如,假设您不想在无法计算z
的情况下打印任何内容(即,None
)。在这种情况下,您可以这样做:
z foreach println