Apache Ni-Fi中如何从InvokeHttp返回的JSON提取无前缀字符串?
嘿,这个需求在Apache Ni-Fi里有好几种实用的实现方式,我给你梳理几个最常用的方案,你可以根据自己的场景来选:
方法1:用JoltTransformJSON处理器(最推荐,纯配置无代码)
这是处理JSON结构转换最省心的方式,完全不用写代码,靠Jolt规范就能搞定:
- 把InvokeHttp输出的JSON流直接传到
JoltTransformJSON处理器 - 配置Jolt Transformation Spec为以下内容:
[ { "operation": "shift", "spec": { "resourceNames": { "*": { "@(0)": { "split('/')": { "1": "customerIds[]" } } } } } } ]
- 简单解释下这个规范:遍历
resourceNames数组里的每一个字符串,用split('/')把它分割成两部分,取索引为1的元素(也就是customers/后面的ID),最后把所有收集到的ID放到新的customerIds数组里 - 处理完成后,输出的JSON就是:
{"customerIds": ["123", "12345", "555", "9890"]},完全符合你的要求
方法2:用UpdateRecord处理器(适合结构化数据场景)
如果你的数据流本身是结构化的,用UpdateRecord来做字段转换也很方便:
- 先定义一个JSON Schema(用来描述输入数据的结构):
{ "type": "record", "name": "CustomerResource", "fields": [ {"name": "resourceNames", "type": {"type": "array", "items": "string"}} ] }
- 配置
UpdateRecord的Record Reader为JsonTreeReader,Record Writer为JsonRecordSetWriter,并把刚才的Schema配置到Reader里 - 在Update策略中添加一个新字段
customerIds,值用Ni-Fi的表达式语言:
${field.value:split('/'):get(1)}
- (可选)如果只需要输出ID数组,可以在Writer的
Fields to Write里只填customerIds,这样就不会保留原有的resourceNames字段
方法3:用ExecuteScript处理器(适合自定义复杂逻辑)
如果需要处理一些特殊情况(比如有的字符串没有/分隔符,或者需要额外的过滤逻辑),可以用脚本自定义处理,这里以Groovy为例:
- 把
ExecuteScript处理器的Script Language设为Groovy - 在Script Body里粘贴以下代码:
import groovy.json.JsonSlurper import groovy.json.JsonBuilder def flowFile = session.get() if (!flowFile) return try { // 读取输入的JSON内容 def slurper = new JsonSlurper() def content = slurper.parseText(flowFile.read().getText()) // 遍历resourceNames,分割字符串取ID部分 def customerIds = content.resourceNames.collect { def parts = it.split('/') parts.size() > 1 ? parts[1] : "" // 加个判断避免空指针 } // 构造输出的JSON def outputJson = new JsonBuilder([customerIds: customerIds]).toPrettyString() // 写回flowfile并传递到成功关系 flowFile = session.write(flowFile, { out -> out.write(outputJson.getBytes('UTF-8')) } as OutputStreamCallback) session.transfer(flowFile, REL_SUCCESS) } catch (e) { log.error("处理JSON时出错: ${e.message}", e) session.transfer(flowFile, REL_FAILURE) }
- 这个脚本会自动处理每个字符串,还加了判断防止没有
/的情况报错,非常灵活
小提示
如果担心输入的resourceNames里有不符合格式的字符串(比如没有/),可以在Jolt或者表达式语言里加容错逻辑,比如在Jolt里用default操作,或者在表达式语言里写:
${field.value:split('/'):size() > 1 ? ${field.value:split('/'):get(1)} : 'invalid-id'}
这样就能避免处理器因为异常数据而失败啦。
内容的提问来源于stack exchange,提问作者funnelCONN
相关产品推荐
相关产品推荐

