Apache NiFi ExecuteScript: Groovy script to replace Json values via a mapping file

后端 未结 1 1761
-上瘾入骨i
-上瘾入骨i 2021-02-20 04:49

I am working with Apache NiFi 0.5.1 on a Groovy script to replace incoming Json values with the ones contained in a mapping file. The mapping file looks like this (it is a simpl

1条回答
  •  青春惊慌失措
    2021-02-20 05:07

    I have some examples on how to read in a flow file containing JSON:

    http://funnifi.blogspot.com/2016/02/executescript-explained-split-fields.html http://funnifi.blogspot.com/2016/05/validating-json-in-nifi-with.html http://funnifi.blogspot.com/2016/02/executescript-processor-replacing-flow.html

    You've got the right structure above; basically you can use that "inputStream" variable in the closure to read the incoming flow file contents. If you want to read it in all at once (which you will likely need to do for JSON), you can use IOUtils.toString() followed by a JsonSlurper, as is done in the examples in the links above.

    For your mapping file, especially if your JSON is "flat", you could have a Java Properties file, mapping the name of the field to the new value:

    field2=some text

    field3=A2

    Check out ConfigSlurper for reading in properties files.

    Once you have slurped the incoming JSON file and read in the mapping file, you can get at the individual fields of the JSON using array notation instead of direct member notation. So let's say I read the properties into a ConfigSlurper, and I want to overwrite any existing property in my input JSON (called "json" for the example) with the one from the properties file. That might look like the following:

    config.parse(props).flatten().each { k,v ->
      if(json[k]) {
        json[k] = v
      }
    }
    

    You can then continue on with your outputStream.write().

    Instead of reading your mappings from a file, you could also load it into a distributed cache via the PutDistributedMapCache processor. You can read from a DistributedCacheMapServer in your ExecuteScript, I have an example here:

    http://funnifi.blogspot.com/2016/04/inspecting-your-nifi.html

    If your mapping is complex, you may want to use the TransformJSON processor, which will be available in the next release of NiFi (0.7.0). The associated Jira case is here:

    https://issues.apache.org/jira/browse/NIFI-361

    EDIT:

    In response to your edits, I didn't realize you had multiple rules for various values. In this case a properties file is probably not the best way to represent the mappings. Instead you could use JSON:

    {
      "field2": {
             "A": "some text",
             "B": "some other text"
           },
      "field3": {
             "A": "A2",
             "B": "B2"
           }
    }
    

    Then you can use a JSONSlurper to read in the mappings file. Here is an example of using the above mapping file:

    import groovy.json.JsonBuilder
    import groovy.json.JsonSlurper
    import org.apache.commons.io.IOUtils
    import org.apache.nifi.processor.io.StreamCallback
    
    import java.nio.charset.StandardCharsets
    
    def flowFile = session.get();
    if (flowFile == null) {
        return;
    }
    
    def mappingJson = new File('/Users/mburgess/mappings.json').text
    
    flowFile = session.write(flowFile, { inputStream, outputStream ->
    
        def content = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
        def inJson = new JsonSlurper().parseText(content)
        def mappings = new JsonSlurper().parseText(mappingJson)
    
        inJson.each {k,v -> 
            inJson[k] = mappings[k][v]
        }
        outputStream.write(inJson.toString().getBytes(StandardCharsets.UTF_8))
    } as StreamCallback)
    
    session.transfer(flowFile, REL_SUCCESS)
    

    0 讨论(0)
提交回复
热议问题