我正在使用Specs2 JSONMatcher来验证GET请求是否正在从其内部表示中正确转换(在生成JSON之前我们做了一些操作)。我需要做的是,确保JSON数组中的元素与我们的存储库中的相应对象匹配。
我尝试了什么:
val response = response.entity.asString // Spray's way of getting the JSON response
repository.all.map { obj =>
resp must */ ("id" -> obj.id)
resp must */ ("state" -> generateState(obj)
}
问题是* / matcher只是发现“状态”:“无论什么”(假设generateState返回“what”)存在于JSON文档的某个地方,不一定是在与ID匹配的同一个
我尝试使用索引,但repository.all方法并不总是以相同的顺序返回元素,因此无法通过索引进行匹配。
我想要做的是,迭代JSON数组的元素并分别匹配每个元素。说一个/ ##运算符(或其他东西),它为每个元素提供匹配器:
resp /## { elem =>
val id = elem("id")
val obj = repository.lookup(id)
elem /("state" -> generateState(obj))
}
有没有人有办法做到这一点或类似的东西?
答案 0 :(得分:1)
现在可能最容易做的事情(直到JsonMatchers
的严重重构)是进行一些解析并递归地使用JsonMatchers
中的Matcher[String]
:
"""{'db' : { 'id' : '1', 'state' : 'ok_1'} }""" must /("db" -> stateIsOk)
// a string matcher for the json string in 'db'
def stateIsOk: Matcher[String] = { json: String =>
// you need to provide a way to access the 'id' field
// then you can go on using a json matcher for the state
findId(json) must beSome { id: String =>
val obj = repository.lookup(id)
json must /("state" -> generate(obj))
}
}
// I am using my own parse function here
def findId(json: String): Option[String] =
parse(json).flatMap { a =>
findDeep("id", a).collect { case JSONArray(List(v)) => v.toString }
}
// dummy system
def generate(id: String) = "ok_"+id
case object repository {
def lookup(id: String) = id
}
答案 1 :(得分:0)
我最后做的是使用responseAs[JArray]
,JArray#arr
和JObject#values
将JSON结构转换为List
和Map
s,然后使用标准的List
和Map
匹配器。更加灵活。