2013-06-05 36 views
1

我试图用下列JSON解析成一个Scala的对象:斯卡拉:重构一个case语句来使用,理解

{ 
    "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) 
         } 
        } 
       } 

我对此语法不满意;即使它工作,我不明白为什么我需要嵌套的匹配语句,如果没有找到匹配。我相信一个理解能够很好地工作:我可以在一个guard子句中检查(json \“allOf”),(json \“oneOf)等等,并产生可用的结果,但不知道如何获得正确的语法。

是否有建立这个案例类更优雅的方式?

感谢,

迈克

回答

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)