You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"
        }
    ]
}

问题原因

  1. 数组覆盖问题:声明def Failed[] fail和def Success[] successful后,每次循环用fail = [failed]直接赋值新数组,完全覆盖之前的内容,导致最终只保留最后一次循环生成的元素。
  2. 属性获取错误:api_response.original.rownum[i]写法错误,original是对象数组,应该先取数组元素再访问属性,即api_response.original[i].rownum,否则会导致索引对应错误。
  3. 匹配与取值逻辑错误: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()

修正说明

  1. 初始化空列表:用def fail = []和def successful = []初始化空列表,循环中用add方法添加元素,避免覆盖。
  2. 构建响应映射:将response数据转成键值对,通过containsKey快速判断是否存在失败记录,同时直接获取对应的错误描述。
  3. 修正属性访问:使用item.rownum直接访问数组元素的属性,避免索引错误。
  4. 统一属性命名:将类中的属性改为小写开头(如status),和JSON序列化后的字段保持一致,避免混淆。

内容的提问来源于stack exchange,提问作者Developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:50:24