2013-11-20 80 views
2

我正在使用Specs2 JSONMatcher來驗證GET請求是否正確地從其內部表示轉換(在生成JSON之前有一些操作)。我需要做的是,確保JSON數組中的元素與我們存儲庫中相應的對象相匹配。Specs2 JSONMatchers:映射數組元素?

我已經試過:

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

的問題是,在* /匹配只是發現「狀態」:「無所謂」(假設generateState返回「無所謂」)存在於JSON文件中的某個地方,不一定在同一個匹配的ID

我試過使用索引,但是repository.all方法並不總是以相同的順序返回元素,所以沒有辦法通過索引進行匹配。

我想要做的是迭代JSON數組的元素並分別匹配每個元素。說,一個/ ##運營商(或某事),其採用的匹配對於每一個元素:

resp /## { elem => 
    val id = elem("id") 
    val obj = repository.lookup(id) 
    elem /("state" -> generateState(obj)) 
} 

沒有人有辦法做到這一點或類似的東西?

回答

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 
} 
0

我到底做了什麼是使用responseAs[JArray]JArray#arrJObject#values將JSON結構轉換爲ListMaps,然後使用標準ListMap匹配器。更靈活。