修复Groovy中的Json格式问题:Apache NiFi ExecuteScript

时间:2016-05-17 09:11:33

标签: groovy apache-nifi

我正在使用Apache Nifi,我的一个流文件是一个稍微不正确的Json:

{
"field" : "value",
"field1" : "value1"

}0;0

我想使用Groovy脚本作为ExecuteScript的一部分,而不是使用之前应用的转换。这就是我现在所拥有的:

import org.apache.nifi.processor.io.StreamCallback
import java.nio.charset.StandardCharsets
import org.apache.commons.io.IOUtils
import java.nio.charset.*


def flowFile = session.get()
if (!flowFile) return

def slurper = new groovy.json.JsonSlurper()

flowFile = session.write(flowFile, { inputStream, outputStream ->
    def text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
    def resultingText = text.substring(0, text.indexOf('}'))
    def json = slurper.parseText(resultingText)

    outputStream.write(json.toString().getBytes(StandardCharsets.UTF_8))

} as StreamCallback)

session.transfer(flowFile, REL_SUCCESS)

但是,我返回时出现以下错误:

ExecuteScript[id=69ae1948-f20b-446c-b33f-298c6faa7c98] Failed to process session due to org.apache.nifi.processor.exception.ProcessException: javax.script.ScriptException: javax.script.ScriptException: groovy.json.JsonException: expecting '}' or ',' but got current char [SPACE] with an int value of 32

The current character read is [SPACE] with an int value of 32
expecting '}' or ',' but got current char [SPACE] with an int value of 32
line number 5
index number 61

...^: org.apache.nifi.processor.exception.ProcessException: javax.script.ScriptException: javax.script.ScriptException: groovy.json.JsonException: expecting '}' or ',' but got current char [SPACE] with an int value of 32

The current character read is [SPACE] with an int value of 32
expecting '}' or ',' but got current char [SPACE] with an int value of 32
line number 5
index number 61

... ^

我做了什么明显错误的事吗?  谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

子字符串的结束索引不包括在内。因此,您需要:

def resultingText = text.substring(0, text.indexOf('}') + 1)

或者,您可以使用groovy中的范围(包括在内)

def resultingText = text[0..text.indexOf('}')]
那是你的结果。没有必要使用JsonSlurper将其解析为地图(除非您只是想验证它是否有效)...并且json.toString()将不会返回您想要的内容,它将返回一个字符串地图的表示

如果您的任何输入json具有嵌套对象,这将会中断: - (

def resultingText = text[0..text.lastIndexOf('}')]

可能会更好: - )

答案 1 :(得分:0)

我最终得到了这个(谢谢@tim_yates):

import org.apache.commons.io.IOUtils
import org.apache.nifi.processor.io.StreamCallback

import java.nio.charset.StandardCharsets

def flowFile = session.get()
if (!flowFile) return

def slurper = new groovy.json.JsonSlurper()

flowFile = session.write(flowFile, { inputStream, outputStream ->
    def text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
    def resultingText = text[0..text.lastIndexOf('}')]
    def json = slurper.parseText(resultingText)

   outputStream.write(json.toString().getBytes(StandardCharsets.UTF_8))

} as StreamCallback)

session.transfer(flowFile, REL_SUCCESS)

发布的示例只是真正的Json的一部分。不幸的是,Json有许多怪癖,例如双引号的价值。例如:

{
 "field" : ""value""
}0;0

以上代码使用以下格式:

{
 "field" : "value"
}0;0

我认为我需要格式化Json然后我可以删除多余的字符。有没有一种简单的方法来确保格式正确?

非常感谢

编辑:

我确实错了,运行脚本后返回的值是:

{field=value}

EDIT。现在正在运作:

import org.apache.commons.io.IOUtils
import org.apache.nifi.processor.io.StreamCallback

import java.nio.charset.StandardCharsets

def flowFile = session.get()
if (!flowFile) return

flowFile = session.write(flowFile, { inputStream, outputStream ->
    def text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
    def resultingText = text[0..text.lastIndexOf('}')].replaceAll('""', '"')

    outputStream.write(resultingText.toString().getBytes(StandardCharsets.UTF_8))

} as StreamCallback)

session.transfer(flowFile, REL_SUCCESS)

但是,数据中仍有许多怪癖会在数据流中造成负担。以下是完整Json的示例:

{"field1": "D",
 "field2": "12345",
 "field3": "myText",
 "field4": ,
 "field5": "B2",
 "field6": "B",
 "field7": 74664",
 "field8": 2,
 "field9": [something."2334", something."9973"],
 "field10": ,
 "field11": "9,
 "field12": "J"}

我设法删除了双“'',但我关注的是右边或左边的值”(例如field7和field11),没有“”的值(例如field8), null值和field9,它应该是["something.2334", "something.9973"]

我想知道如何确保Json的格式正确(例如,稍后摄入Db)。

非常感谢