在Karate中如何用单行语句匹配JSON数组子集与超集
问题:验证JSON子集与超集的对象匹配(处理键大小写与类型差异)
需要验证JSON子集数组中每个对象的所有属性值,是否能匹配超集数组中的对应对象,需处理两处差异:
- 键的大小写不同(子集为小驼峰/小写,超集为全大写)
- 子集的
grade为浮点型,超集的GRADE为字符串型
尝试用match each结合karate.jsonPath实现但未成功,希望找到除自定义函数外的单行简化方案。
示例数据
子集JSON数组
def subSet = [{userName: "JohnSmith", firstName: "John", lastName: "Smith", grade: 6.7}, {userName: "JohnDoe", firstName: "John", lastName: "Doe", grade: 6.9}, {userName: "WillSmith", firstName: "Will", lastName: "Smith", grade: 6.5}]
超集JSON数组
def superSet = [{USERNAME: "JohnSmith", FIRSTNAME: "John", LASTNAME: "Smith", GRADE: "6.7"}, {USERNAME: "BruceWayne", FIRSTNAME: "Bruce", LASTNAME: "Wayne", GRADE: "6.2"}, {USERNAME: "JohnDoe", FIRSTNAME: "John", LASTNAME: "Doe", GRADE: "6.9"}, {USERNAME: "JaneDoe", FIRSTNAME: "Jane", LASTNAME: "Doe", GRADE: "6.1"}, {USERNAME: "WillSmith", FIRSTNAME: "Will", LASTNAME: "Smith", GRADE: "6.5"}]
尝试过的无效写法
* match each subSet contains {grade: '#? _ == karate.jsonPath(superSet, "$[?(@.FIRSTNAME == _$.firstName && @.LASTNAME == _$.lastName)]")[0].GRADE * 1'}
可行的单行匹配方案
可以利用Karate的karate.find()函数(比JSONPath更灵活,支持直接引用当前对象),结合#?表达式实现单行验证:
* match each subSet == '#? let matchItem = karate.find(superSet, x => x.USERNAME == _.userName && x.FIRSTNAME == _.firstName && x.LASTNAME == _.lastName); matchItem != null && parseFloat(matchItem.GRADE) == _.grade'
方案说明
karate.find(superSet, x => ...):从超集中筛选出与当前子集对象_匹配的对象(通过USERNAME、FIRSTNAME、LASTNAME三个键匹配)matchItem != null:确保超集中存在对应的对象parseFloat(matchItem.GRADE) == _.grade:将超集中的字符串类型GRADE转换为浮点数,与子集的浮点型grade做等值校验
原写法失败原因
你之前用karate.jsonPath的写法无法生效,是因为JSONPath的查询字符串是静态文本,Karate不会解析其中的_$变量(当前子集对象),导致无法动态匹配对应属性。而karate.find()支持Lambda表达式,可以直接引用_(当前迭代的子集对象),避免了作用域问题。
内容的提问来源于stack exchange,提问作者Avirup Das
相关产品推荐
相关产品推荐

