Scala:重构一个case语句以用于理解

时间:2013-06-05 15:25:39

标签: json scala refactoring playframework-2.0

我正在尝试将以下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>

有没有更优雅的方法来构建这个案例类?

谢谢,

麦克

1 个答案:

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