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

NiFi 1.16.3中ExecuteGroovyScript脚本触发NumberFormatException求助

解决NiFi ExecuteGroovyScript的NumberFormatException问题

问题场景

在NiFi 1.16.3中使用ExecuteGroovyScript处理器,将固定长度格式的文本FlowFile转换为JSON时,执行过程中持续抛出NumberFormatException错误。

样本输入文本

+0002150736YY+0701748361MN      0001-01-01SSD+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000-000000000002860+000000000000000+000000000000000     1+0000000000000002023-05-23+0701748361
+0002152097XX+0701763467RR      0001-01-01SSF+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000011845+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000+000000000000000     1+0000000000000002023-05-23+0701763467

报错信息

All NodesExecuteGroovyScript[id=afb7a99f-0188-1000-0000-00004af5fb62] java.lang.NumberFormatException: java.lang.NumberFormatException

问题排查

原脚本的核心问题在于字段截取范围错误和数字转换未做安全校验:

  1. 固定长度字段的索引截取与实际文本不匹配,导致截取到的字符串包含非数字字符(比如字母、空格),调用toBigDecimal()时抛出格式异常。
  2. 未处理空字符串或无效数字的情况,即使截取范围正确,若字段为空或包含非数字内容,直接转换也会报错。

修正后的Groovy脚本

import groovy.json.JsonBuilder
import java.nio.charset.StandardCharsets
import java.time.LocalDate
import java.time.format.DateTimeParseException

def flowFile = session.get()
if (flowFile) {
    def datePattern = java.time.format.DateTimeFormatter.ofPattern('yyyy-MM-dd')
    def records = []

    flowFile.read().withReader('ISO-8859-1') { reader ->
        reader.eachLine { line ->
            // 安全转换为BigDecimal的工具方法
            def safeToBigDecimal = { str ->
                def trimmed = str?.trim()
                trimmed && trimmed.matches(/[+-]?\d+/) ? new BigDecimal(trimmed) : null
            }
            
            // 安全解析日期的工具方法
            def safeParseDate = { str ->
                def trimmed = str?.trim()
                if (!trimmed || trimmed == '0000-00-00') return null
                try {
                    LocalDate.parse(trimmed, datePattern)
                } catch (DateTimeParseException e) {
                    null
                }
            }

            def record = [
                SEQ_LD: 'ADMIN.SEQ_INFO.NEXTVAL',
                NO: safeToBigDecimal(line[0..10]),
                PA: line[11..12]?.trim() ?: '',
                PAR: safeToBigDecimal(line[13..23]),
                CD: line[24..27]?.trim() ?: '',
                CFOUR: line[28..31]?.trim() ?: '',
                DTIR: safeParseDate(line[32..41]),
                DEV: line[42..44]?.trim() ?: '',
                EXBL: safeToBigDecimal(line[45..60]),
                NEXBL: safeToBigDecimal(line[61..76]),
                SUSP: safeToBigDecimal(line[77..92]),
                NEXBL_SUSP: safeToBigDecimal(line[93..108]),
                SOLC: safeToBigDecimal(line[109..124]),
                MXBL: safeToBigDecimal(line[125..140]),
                MMIX: safeToBigDecimal(line[141..156]),
                ABD: safeToBigDecimal(line[157..172]),
                EXBLFF: safeToBigDecimal(line[173..188]),
                MTGR: safeToBigDecimal(line[189..204]),
                MKLM: safeToBigDecimal(line[205..220]),
                MXYR: safeToBigDecimal(line[221..236]),
                MHHH: safeToBigDecimal(line[237..252]),
                MOPO: safeToBigDecimal(line[253..268]),
                MNBFR: safeToBigDecimal(line[269..284]),
                CGTRH: line[285..289]?.trim() ?: '',
                IPOING: line[290..290]?.trim() ?: '',
                BGFTU: safeToBigDecimal(line[291..306]),
                DLJHJ: safeParseDate(line[307..316]),
                NHJGY: safeToBigDecimal(line[317..327]),
                AACBT: line[328..328]?.trim() ?: '',
                TRT: LocalDate.parse('2023-06-05', datePattern)
            ]
            records << record
        }
    }

    def json = new JsonBuilder(records)
    def jsonBytes = json.toString().getBytes(StandardCharsets.UTF_8)
    flowFile = session.write(flowFile, { outputStream ->
        outputStream.write(jsonBytes)
    } as OutputStreamCallback)

    flowFile = session.putAttribute(flowFile, 'filename', 'output.json')
    session.transfer(flowFile, REL_SUCCESS)
}

关键修改说明

  • 添加安全转换工具方法:
    • safeToBigDecimal:先校验字符串是否为有效数字格式,只有符合规则才转换,否则返回null,彻底避免NumberFormatException。
    • safeParseDate:添加try-catch捕获日期解析异常,同时处理空字符串和无效日期(如0000-00-00),返回null而非抛出错误。
  • 字段截取验证:需根据实际文本的固定长度确认每个字段的索引范围,若样本文本的字段长度与原脚本假设不符,需重新调整line[start..end]的索引值,确保截取到的是纯数字内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:02:02