我正在尝试将以下Json解析为Scala对象:
{
"oneOf": [
{ "$ref": "..." },
{ "$ref": "..." },
{ "$ref": "..." }
}
字段“oneOf”也可以是“anyOf”或“allOf”;它只会是这些价值之一。我正在使用Play的JSON库构建一个案例类ComplexType。逻辑很简单;它查找给定的字段并在存在时读取它,否则,检查不同的字段。
(json \ "allOf") match {
case a:JsArray => ComplexType("object", "allOf", a.as[Seq[JsObject]].flatMap(_.values.map(_.as[String])))
case _ =>
(json \ "anyOf") match {
case a:JsArray => ComplexType("object", "anyOf", a.as[Seq[JsObject]].flatMap(_.values.map(_.as[String])))
case _ =>
(json \ "oneOf") match {
case a:JsArray => ComplexType("object", "oneOf", a.as[Seq[JsObject]].flatMap(_.values.map(_.as[String])))
case _ => ComplexType("object", "oneOf", "Unspecified" :: Nil)
}
}
}
我对这种语法不满意;即使它工作,我不明白为什么我需要嵌套的匹配语句,如果没有找到匹配。我相信for-comprehension可以很好地工作:我可以在一个保护子句中检查(json \“allOf”),(json \“oneOf)等并产生可用的结果,但不确定如何使语法正确。< / p>
有没有更优雅的方法来构建这个案例类?
谢谢,
麦克
答案 0 :(得分:2)
我不认为理解在这里很有用。
您可以使用以下自定义提取程序使代码更具可读性:
class Extractor(s: String) {
def unapply(v: JsValue): Option[JsArray] = json \ s match {
case a: JsArray => Some(a)
case _ => None
}
}
val AllOf = new Extractor("allOf")
val AnyOf = new Extractor("anyOf")
val OneOf = new Extractor("oneOf")
val (name, es) = json match {
case AllOf(a) => "allOf" -> Some(a)
case AnyOf(a) => "anyOf" -> Some(a)
case OneOf(a) => "oneOf" -> Some(a)
case _ => "oneOf" -> None
}
val result =
es.
map{ a => ComplexType("object", name, a.as[Seq[JsObject]].flatMap(_.values.map(_.as[String]))) }.
getOrElse("Unspecified" :: Nil)