【问题标题】:Play Json - Compare nested Json-Array with Specs2Play Json - 将嵌套的 Json-Array 与 Specs2 进行比较
【发布时间】:2016-02-16 22:51:46
【问题描述】:

使用 Play-Json 和 Specs2,我可以像这样匹配 json-body:

contentAsJson(res) must equalTo(responseBody)

是否有可能忽略 json-arrays 的顺序(递归),而是将 json-arrays 的相等性视为集合?

【问题讨论】:

    标签: playframework specs2 play-json


    【解决方案1】:

    这涉及到一些工作,具体取决于您希望失败消息有多好。你可以这样做

    import org.specs2._
    import execute._
    import matcher._
    import play.api.libs.json._
    
    trait JsValueMatchers extends MustMatchers {
      def beEqualj(expected: JsValue): Matcher[JsValue] = { actual: JsValue =>
        (actual, expected) match {
          case (JsArray(as), JsArray(es)) =>
            asPair(as must contain(allOf(es.map(beEqualj):_*)).exactly)
    
          case (JsObject(as), JsObject(es)) =>
            asPair(as must contain(allOf(es.toList.map(pairEqualj):_*)).exactly.inOrder)
    
          case (JsNull, JsNull) =>
            (true, "ko")
    
          case (JsBoolean(a), JsBoolean(e)) =>
            (a == e, s"ko: $a is not equal to $e")
    
          case (JsString(a), JsString(e)) =>
            (a == e, s"ko: $a is not equal to $e")
    
          case (JsNumber(a), JsNumber(e)) =>
            (a == e, s"ko: $a is not equal to $e")
    
          case _ =>
            (false, s"$actual and $expected don't have the same type")
        }
      }
    
      def pairEqualj(expected: (String, JsValue)): Matcher[(String, JsValue)] = { actual: (String, JsValue) =>
        val (key, value) = actual
        val result = (key must_== expected._1) and
          (value must beEqualj(expected._2))
        asPair(result)
      }
    
      def asPair[R : AsResult](r: R): (Boolean, String) = {
        val result = AsResult(r)
        (result.isSuccess, result.message)
      }
    }
    
    object JsValueMatchers
    

    【讨论】:

    • 非常感谢。看起来很有希望。尝试编译时我只得到 1 个错误:found : Iterable[org.specs2.matcher.Matcher[(String, play.api.libs.json.JsValue)]] required: Seq[org.specs2.matcher.ValueCheck[?]] Read from stdout: asPair(as must contain(allOf(es.map(pairEqualj):_*)).exactly.inOrder)
    • 抱歉,我现在修复了编译错误。
    【解决方案2】:

    您可以将 json 转换为案例类并将它们作为集合进行比较:

    contentAsJson(res).as[Set[User]] must equalTo(Json.parse(responseBody).as[Set[User]])
    

    【讨论】:

    • 可选字段呢?假设我们的 JSON 可以有一个可选的“时间”字段,假设我们有两个完全相同但只有一个字段的 JSON。 json1 没有 time 字段,json2null time 值,例如 {..., "time": null, ...}。在这种情况下,案例类将是相同的,但 JSON 并不完全相同。
    • 在 JSON 中使用 null 值可能没有意义,但这是可能的 :)
    • 确实 json 文档不会完全相同,但 null 仍然是有效的 json 文档。如果解析器是 json 兼容的,它们在语义上是相同的。不过你有道理。这更像是一种快速而肮脏的方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多