在scala中解析嵌套集合

时间:2019-05-24 16:04:40

标签: json scala collections

我具有如下所示的收集结构。我需要基于地图中的k,v对构建语句。嵌套的级别事先未知,因此代码需要动态地对其进行解析。

结构:

case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])

    val sample = Step(id = Some("a1"), Some("case"), Some(
        Map(
            "CONDITIONAL" -> List(
                Map("comparison" -> List(
                    Map("comparision" -> List(
                        Map("comparision" -> List(
                            Map("comparator" -> List(
                                Map(
                                    "EVAL" -> "c11",
                                    "OPERATION" -> "equals to",
                                    "WHEN" -> List("A")),
                                Map(
                                    "eval" -> "c12",
                                    "operation" -> "in",
                                    "when" -> List("B")),
                                Map(
                                    "eval" -> "c13",
                                    "operation" -> "starts with",
                                    "when" -> List("C")
                                )),
                                "operator" -> "OR"
                            ),
                            Map("comparator" -> List(
                                Map(
                                    "EVAL" -> "c21",
                                    "OPERATION" -> "equals to",
                                    "WHEN" -> List("A")),
                                Map(
                                    "eval" -> "c22",
                                    "operation" -> "in",
                                    "when" -> List("B")
                                )),
                                "operator" -> "OR"
                            )),
                            "operator" -> "AND"
                        ),
                        Map("comparator" -> List(
                            Map(
                                "EVAL" -> "c31",
                                "OPERATION" -> "equals to",
                                "WHEN" -> List("A")),
                            Map(
                                "EVAL" -> "c32",
                                "OPERATION" -> "in",
                                "WHEN" -> List("B")),
                            Map(
                                "EVAL" -> "c33",
                                "OPERATION" -> "starts with",
                                "WHEN" -> List("C")
                            )),
                            "operator" -> "OR"
                        )),
                        "operator" -> "OR"
                    )),
                    "THEN" -> "result"
                )),
            "ELSE" -> "default"
        ))
    )

val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)

val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]

现在,我需要通过评估结构来分析条件下的数据(比较)。

结果应为((c11 OR c12 OR c13)AND(c21 OR c22))OR(c31 OR c32 OR c33 OR c34)

1 个答案:

答案 0 :(得分:0)

这是适用于所有用例的代码段。

case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])

val sample1 = Step(id = Some("a1"), Some("case"), Some(Map(
    "CONDITIONAL" -> List(
      Map("comparison" -> List(
        Map("comparison" -> List(
          Map("comparison" -> List(
            Map("comparator" -> List(
              Map(
                "eval" -> "c11",
                "operation" -> "equals to",
                "when" -> List("A")),
              Map(
                "eval" -> "c12",
                "operation" -> "in",
                "when" -> List("B")),
              Map(
                "eval" -> "c13",
                "operation" -> "starts with",
                "when" -> List("C")
              )),
              "operator" -> "OR"
            ),
            Map("comparator" -> List(
              Map(
                "eval" -> "c21",
                "operation" -> "equals to",
                "when" -> List("A")),
              Map(
                "eval" -> "c22",
                "operation" -> "in",
                "when" -> List("B")
              )),
              "operator" -> "OR"
            )),
            "operator" -> "AND"
          ),
          Map("comparator" -> List(
            Map(
              "eval" -> "c31",
              "operation" -> "equals to",
              "when" -> List("A")),
            Map(
              "eval" -> "c32",
              "operation" -> "in",
              "when" -> List("B")),
            Map(
              "eval" -> "c33",
              "operation" -> "starts with",
              "when" -> List("C")
            )),
            "operator" -> "OR"
          )),
          "operator" -> "OR"
        )),
        "then" -> "result"
      )),
    "else" -> "default"
  ))
)


val sample2 = Step(id = Some("a1"), Some("case"), Some(
  Map(
    "conditional" -> List(
      Map("comparison" -> List(
        Map("comparison" -> List(
          Map("comparator" -> List(
            Map(
              "eval" -> "c11",
              "operation" -> "equals to",
              "when" -> List("A")),
            Map(
              "eval" -> "c12",
              "operation" -> "in",
              "when" -> List("B", "b"))),
            "operator" -> "AND"),
          Map("comparator" -> List(
            Map("eval" -> "c21",
              "operation" -> "equals to",
              "when" -> List("A")),
            Map("eval" -> "c31",
              "operation" -> "equals to",
              "when" -> List("A"))),
            "operator" -> "OR")),
          "operator" -> "OR")),
        "then" -> "something"
      ),
      Map("comparison" -> List(
        Map("comparison" -> List(
          Map("comparator" -> List(
            Map(
              "eval" -> "c111",
              "operation" -> "equals to",
              "when" -> List("A")),
            Map(
              "eval" -> "c121",
              "operation" -> "in",
              "when" -> List("B", "b"))
          ),
            "operator" -> "AND"),
          Map("comparator" -> List(
            Map(
              "eval" -> "c212",
              "operation" -> "equals to",
              "when" -> List("A")),
            Map(
              "eval" -> "c313",
              "operation" -> "equals to",
              "when" -> List("A"))
          ),
            "operator" -> "OR")),
          "operator" -> "AND")),
        "then" -> "somethingelse")
    ),
    "else" -> "default"
  )
))



def constructCase(c: List[Map[String, Any]], parentOp: Option[String] = None, parentThen: Option[String] = None): String = {

  val result = c.map { x =>
    val currentOp: Option[String] = x.get("operator").asInstanceOf[Option[String]]
    val currentThen: Option[String] = x.get("then").asInstanceOf[Option[String]]

    if (x contains "comparator") {
      "(" + x("comparator").asInstanceOf[List[Map[String, Any]]].map(x => s"${x("eval")} ${x("operation")} ${x("when").asInstanceOf[List[String]].mkString(",")}").mkString(" " + currentOp.getOrElse("") + " ") + ")"
    } else {
      val tmp = constructCase(x("comparison").asInstanceOf[List[Map[String, Any]]], currentOp, currentThen)
      if (tmp contains "WHEN") tmp else "(" + tmp + ")"
    }
  }.mkString(if (parentOp.isDefined) s" ${parentOp.get} " else "")

  if (parentThen.isDefined) s"WHEN $result THEN ${parentThen.get}\n" else result.trim
}

val samples = Set(sample1, sample2)
samples.foreach { sample =>
  val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)

  val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]

  println("CASE \n" + constructCase(comparisons) + s"\nELSE ${stepsLower("else")}")
  println("")
}
  

这是结果

CASE 
WHEN (((c11 equals to A OR c12 in B OR c13 starts with C) AND (c21 equals to A OR c22 in B)) OR (c31 equals to A OR c32 in B OR c33 starts with C)) THEN result
ELSE default

CASE 
WHEN ((c11 equals to A AND c12 in B,b) OR (c21 equals to A OR c31 equals to A)) THEN something
WHEN ((c111 equals to A AND c121 in B,b) AND (c212 equals to A OR c313 equals to A)) THEN somethingelse
ELSE default

让我知道它是否不适用于您的任何用例。