JMeter从JSON响应提取大量账户名称时报错求助
JMeter JSR223脚本提取账户名称报错解决
问题背景
尝试从JSON响应体中提取所有账户名称时,JSR223脚本执行报错,最初怀疑是数据量过大导致,实际为语法使用错误。
原错误代码
import groovy.json.JsonSlurper; def responseBD = new groovy.json.JsonSlurper().parse(prev.getResponseData()); def studyName = []; responseBD.accounts.name { studyNameFetched-> //studyName << studyNameFetched log.info("Reference Value : "+studyNameFetched) }
错误详情
2023-05-30 12:11:22,577 INFO o.a.j.e.StandardJMeterEngine: Running the test! 2023-05-30 12:11:22,577 INFO o.a.j.s.SampleEvent: List of sample_variables: [] 2023-05-30 12:11:22,577 INFO o.a.j.g.u.JMeterMenuBar: setRunning(true, *local*) 2023-05-30 12:11:22,619 INFO o.a.j.e.StandardJMeterEngine: Starting ThreadGroup: 1 : Thread Group 2023-05-30 12:11:22,619 INFO o.a.j.e.StandardJMeterEngine: Starting 1 threads for group Thread Group. 2023-05-30 12:11:22,619 INFO o.a.j.e.StandardJMeterEngine: Thread will continue on error 2023-05-30 12:11:22,619 INFO o.a.j.t.ThreadGroup: Starting thread group... number=1 threads=1 ramp-up=1 delayedStart=false 2023-05-30 12:11:22,624 INFO o.a.j.t.ThreadGroup: Started thread group number 1 2023-05-30 12:11:22,624 INFO o.a.j.e.StandardJMeterEngine: All thread groups have been started 2023-05-30 12:11:22,624 INFO o.a.j.t.JMeterThread: Thread started: Thread Group 1-1 2023-05-30 12:12:14,933 ERROR o.a.j.e.JSR223PostProcessor: Problem in JSR223 script, JSR223 PostProcessor javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.name() is applicable for argument types: (Script8$_run_closure1) values: [Script8$_run_closure1@68c01c8b] Possible solutions: any(), max(), take(int), take(int), wait(), size() at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320) ~[groovy-jsr223-3.0.11.jar:3.0.11] at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:71) ~[groovy-jsr223-3.0.11.jar:3.0.11] at javax.script.CompiledScript.eval(CompiledScript.java:93) ~[java.scripting:?] at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:217) ~[ApacheJMeter_core.jar:5.5] at org.apache.jmeter.extractor.JSR223PostProcessor.process(JSR223PostProcessor.java:45) ~[ApacheJMeter_components.jar:5.5] at org.apache.jmeter.threads.JMeterThread.runPostProcessors(JMeterThread.java:968) ~[ApacheJMeter_core.jar:5.5] at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:585) ~[ApacheJMeter_core.jar:5.5] at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.5] at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.5] at java.lang.Thread.run(Thread.java:833) ~[?:?] Caused by: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.name() is applicable for argument types: (Script8$_run_closure1) values: [Script8$_run_closure1@68c01c8b] Possible solutions: any(), max(), take(int), take(int), wait(), size() at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:70) ~[groovy-3.0.11.jar:3.0.11] at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46) ~[groovy-3.0.11.jar:3.0.11] at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) ~[groovy-3.0.11.jar:3.0.11] at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) ~[groovy-3.0.11.jar:3.0.11] at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139) ~[groovy-3.0.11.jar:3.0.11] at Script8.run(Script8.groovy:7) ~[?:?] at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317) ~[groovy-jsr223-3.0.11.jar:3.0.11] ... 9 more 2023-05-30 12:12:14,936 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group 1-1 2023-05-30 12:12:14,936 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group 1-1 2023-05-30 12:12:14,937 INFO o.a.j.e.StandardJMeterEngine: Notifying test listeners of end of test 2023-05-30 12:12:14,937 INFO o.a.j.g.u.JMeterMenuBar: setRunning(false, *local*)
响应数据示例
{ "page": { "number": 1, "more": 0, "rows": 5000 }, "accounts": [ { "name": "Enterprise Site Management", "uuid": "6656dae1-159a-4062-9cbb-5382d5202cd8" }, { "name": "R2_Single QC", "uuid": "197650ca-d8fc-451d-9332-50d801b5c426" }, { "name": "GUAC", "uuid": "ac7adabd-8040-498b-87ed-9c69d678ad49" }, { "name": "PushkarTIMS-0501", "uuid": "0210da27-1724-40bb-a618-005103bb5970" }, { "name": "ppp", "uuid": "8b982528-5fef-49d6-a016-e56c1de25c89" } ] }
错误原因
报错核心是groovy.lang.MissingMethodException,说明responseBD.accounts是ArrayList类型,不能直接调用name()方法并传入闭包。原代码试图直接对数组调用name方法遍历,不符合Groovy语法规范。
当前报错和数据量无关,只要语法正确,即使响应包含5000条数据也能正常处理(若数据量极大,可考虑优化内存,但当前问题不涉及)。
修正后的脚本
方式1:遍历数组提取名称并打印
import groovy.json.JsonSlurper def responseBD = new JsonSlurper().parse(prev.getResponseData()) def accountNames = [] // 遍历accounts数组,提取每个元素的name属性 responseBD.accounts.each { account -> def name = account.name accountNames << name log.info("账户名称: ${name}") } // 可选:将提取的名称存储为JMeter变量,方便后续使用 vars.putObject("accountNames", accountNames)
方式2:快速提取所有名称到列表(更简洁)
import groovy.json.JsonSlurper def responseBD = new JsonSlurper().parse(prev.getResponseData()) def accountNames = responseBD.accounts.name // Groovy支持直接对数组提取属性,返回属性列表 accountNames.each { name -> log.info("账户名称: ${name}") } vars.putObject("accountNames", accountNames)
说明
- 两种方式都能正确提取所有账户名称,方式2利用Groovy特性更简洁;
- 若后续需要使用提取的名称列表,可通过
vars.putObject存储,在其他组件中通过${__groovy(vars.getObject("accountNames"),)}调用; - 若数据量超过万级,建议使用
JsonSlurperClassic替代JsonSlurper以减少内存占用,但当前5000条数据无需调整。
内容的提问来源于stack exchange,提问作者Jyoti Prakash Mallick
相关产品推荐
相关产品推荐

