Groovy脚本对象被覆盖问题:按索引匹配数据异常求助
问题:Groovy脚本数组元素被覆盖,仅保留最后一条记录
我是Groovy新手,运行脚本时遇到对象被覆盖的问题。需求是根据original数组的索引计数,匹配response字段对应的数据,但输出仅保留最后一条记录,求排查原因并修正。
原脚本
import groovy.json.JsonSlurper import groovy.json.JsonBuilder import groovy.json.* import java.nio.charset.* response_api = """{ "original" : [ { "inp1" : 18, "id" : 184000, "rownum" : 123 }, { "inp1" : 18, "id" : 184001, "rownum" : 121 }, { "inp1" : 19, "id" : 184002, "rownum" : 124 } ] , "response" : [ { "Record" : "Record 2", "Description" : "Internal Server Error." }, { "Record" : "Record 3", "Description" : "Processing failed due to record 2" } ] }""" class Result{ Success[] SuccessRecords Failed[] FailedRecords public Result( Success[] SuccessRecords, Failed[] FailedRecords){ this.SuccessRecords = SuccessRecords this.FailedRecords = FailedRecords } } class Success{ int rownum int inp1 String Status public Success(int rownum, int inp1,String Status){ this.rownum = rownum this.inp1 = inp1 this.Status = Status } } class Failed{ int rownum int inp1 String Status String ErrorDescription public Failed(int rownum, int inp1,String Status,String ErrorDescription){ this.rownum = rownum this.inp1 = inp1 this.Status = Status this.ErrorDescription = ErrorDescription } } def Failed[] fail def Success[] successful def api_response = new JsonSlurper().parseText(response_api) int j = api_response.original.size() for (int i=0;i<j;i++){ index = i+1 def rec = 'Record ' + index if (rec in api_response.response.Record){ Failed failed = new Failed(api_response.original.rownum[i],api_response.original.inp1[i],"Failed",api_response.response.Description[i]) fail = [failed] } else { Success success = new Success(api_response.original.rownum[i],api_response.original.inp1[i],"Success") successful = [success] } } def Result myJson = new Result(successful,fail) def finalJson = new JsonBuilder(myJson) println finalJson.toPrettyString()
实际输出
{ "failedRecords": [ { "errorDescription": null, "status": "Failed", "rownum": 124, "inp1": 19 } ], "successRecords": [ { "status": "Success", "rownum": 123, "inp1": 18 } ] }
预期输出
{ "failedRecords": [ { "rownum": 121, "inp1": 18, "status": "Failed", "errorDescription":"Internal Server Error." }, { "rownum": 124, "inp1": 19, "status": "Failed", "errorDescription": "Processing failed due to record 2" } ], "successRecords": [ { "rownum": 123, "inp1": 18, "status": "Success" } ] }
问题原因
- 数组覆盖问题:声明
def Failed[] fail和def Success[] successful后,每次循环用fail = [failed]直接赋值新数组,完全覆盖之前的内容,导致最终只保留最后一次循环生成的元素。 - 属性获取错误:
api_response.original.rownum[i]写法错误,original是对象数组,应该先取数组元素再访问属性,即api_response.original[i].rownum,否则会导致索引对应错误。 - 匹配与取值逻辑错误:
rec in api_response.response.Record无法正确匹配,且api_response.response.Description[i]会因为response数组长度比original短,导致取到错误的描述甚至null。
修正后的脚本
import groovy.json.JsonSlurper import groovy.json.JsonBuilder response_api = """{ "original" : [ { "inp1" : 18, "id" : 184000, "rownum" : 123 }, { "inp1" : 18, "id" : 184001, "rownum" : 121 }, { "inp1" : 19, "id" : 184002, "rownum" : 124 } ] , "response" : [ { "Record" : "Record 2", "Description" : "Internal Server Error." }, { "Record" : "Record 3", "Description" : "Processing failed due to record 2" } ] }""" class Result{ Success[] successRecords Failed[] failedRecords public Result(Success[] successRecords, Failed[] failedRecords){ this.successRecords = successRecords this.failedRecords = failedRecords } } class Success{ int rownum int inp1 String status public Success(int rownum, int inp1, String status){ this.rownum = rownum this.inp1 = inp1 this.status = status } } class Failed{ int rownum int inp1 String status String errorDescription public Failed(int rownum, int inp1, String status, String errorDescription){ this.rownum = rownum this.inp1 = inp1 this.status = status this.errorDescription = errorDescription } } // 初始化空列表,用于收集结果 def fail = [] def successful = [] def api_response = new JsonSlurper().parseText(response_api) // 将response转成Record到Description的映射,方便快速查找 def responseMap = api_response.response.collectEntries { [(it.Record): it.Description] } api_response.original.eachWithIndex { item, index -> int recordNum = index + 1 def recKey = "Record ${recordNum}" if (responseMap.containsKey(recKey)) { // 找到匹配的失败记录,添加到列表 Failed failed = new Failed(item.rownum, item.inp1, "Failed", responseMap[recKey]) fail.add(failed) } else { // 无匹配,添加成功记录 Success success = new Success(item.rownum, item.inp1, "Success") successful.add(success) } } def Result myJson = new Result(successful as Success[], fail as Failed[]) def finalJson = new JsonBuilder(myJson) println finalJson.toPrettyString()
修正说明
- 初始化空列表:用
def fail = []和def successful = []初始化空列表,循环中用add方法添加元素,避免覆盖。 - 构建响应映射:将response数据转成键值对,通过
containsKey快速判断是否存在失败记录,同时直接获取对应的错误描述。 - 修正属性访问:使用
item.rownum直接访问数组元素的属性,避免索引错误。 - 统一属性命名:将类中的属性改为小写开头(如
status),和JSON序列化后的字段保持一致,避免混淆。
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

