Karate访问数字字符串为键的JSON属性报错,求解决方案
Karate中访问数字键JSON属性的语法问题及解决方法
问题场景
从API获取到如下JSON响应:
{ "lanes": [ { "laneId": "6ef9deb2-de6d-43f7-baed-fe00de3a11d4", "name": "LaneTest", "dayShifts": { "1": [ "Morning Shift" ] } }, { "laneId": "559165e9-d675-4537-99e7-a0f3b73de3c8", "name": "testaaa", "dayShifts": { "1": [ "11am shift", "5:00 pm shift" ] } }] }
尝试筛选出dayShifts.1数组中包含"Morning Shift"的lane对象,编写了如下Karate代码:
* def shiftFilter = function(x) { return x == 'Morning Shift' } * def laneIdFilter = function(x) { return karate.filter(x.dayShifts.1, shiftFilter) } * def laneObj = karate.filter(response.lanes, laneIdFilter)
执行后出现语法错误:
>>>> failed features: js failed: >>>>>> 01: (function(x) { return karate.filter(x.dayShifts.1, shiftFilter) }) <<<<<< org.graalvm.polyglot.PolyglotException: SyntaxError: Unnamed:1:47 Expected , but found .1 (function(x) { return karate.filter(x.dayShifts.1, shiftFilter) }) ^ Unnamed:1:65 Expected ; but found ) (function(x) { return karate.filter(x.dayShifts.1, shiftFilter) }) ^ Unnamed:1:66 Expected } but found eof (function(x) { return karate.filter(x.dayShifts.1, shiftFilter) }) ^ - org.graalvm.polyglot.Context.eval(Context.java:425) - com.intuit.karate.graal.JsEngine.evalForValue(JsEngine.java:139) - com.intuit.karate.graal.JsEngine.eval(JsEngine.java:135) - com.intuit.karate.core.ScenarioEngine.evalJs(ScenarioEngine.java:1190) - com.intuit.karate.core.ScenarioEngine.evalKarateExpression(ScenarioEngine.java:2143) - com.intuit.karate.core.ScenarioEngine.evalKarateExpression(ScenarioEngine.java:2062) - com.intuit.karate.core.ScenarioEngine.evalAndCastTo(ScenarioEngine.java:1251)
筛选lane对象的其他属性(如name)时可正常运行,问题出在dayShifts对象的数字键"1"的访问方式上,使用Karate v1.3.0版本。
原因分析
在JavaScript(Karate内置JS引擎遵循JS语法)中,无法直接用.访问以数字开头的属性键,必须使用方括号语法访问这类属性。x.dayShifts.1不符合JS语法规范,因此抛出语法错误。
解决方法
修改laneIdFilter函数,将x.dayShifts.1替换为x.dayShifts['1'],同时优化过滤逻辑:原代码中karate.filter返回过滤后的数组,需判断数组长度是否大于0,确保只保留包含目标班次的lane对象。
修正后的代码如下:
* def shiftFilter = function(x) { return x == 'Morning Shift' } * def laneIdFilter = function(x) { return karate.filter(x.dayShifts['1'], shiftFilter).length > 0 } * def laneObj = karate.filter(response.lanes, laneIdFilter)
或者更简洁的写法,直接用includes方法判断数组是否包含目标值:
* def laneIdFilter = function(x) { return x.dayShifts['1'].includes('Morning Shift') } * def laneObj = karate.filter(response.lanes, laneIdFilter)
补充说明
如果需要在Karate表达式中访问数字键属性,同样可以使用方括号语法,比如直接提取某个lane的目标班次数组:
* def morningShifts = response.lanes[0].dayShifts['1']
内容的提问来源于stack exchange,提问作者pooventhan
相关产品推荐
相关产品推荐

