title: Complex transformations and filters with Apache NiFi
body: <p>I have a JSON array:</p>
  <pre><code>[ {
    &quot;account_login&quot; : &quot;some_mail@gmail.com&quot;,
    &quot;view_id&quot; : 11313231,
    &quot;join_id&quot; : &quot;utm_campaign=toyota&amp;utm_content=multiformat_sites&amp;utm_medium=cpc&amp;utm_source=mytarget&quot;,
    &quot;start_date&quot; : &quot;2020-08-01&quot;,
    &quot;end_date&quot; : &quot;2020-08-31&quot;
  }, {
    &quot;account_login&quot; : &quot;another_mail@lab.net&quot;,
    &quot;view_id&quot; : 19556319183,
    &quot;join_id&quot; : &quot;utm_campaign=mazda&amp;utm_content=keywords_social-networks&amp;utm_medium=cpc&amp;utm_source=facebook&quot;,
    &quot;start_date&quot; : &quot;2020-12-22&quot;,
    &quot;end_date&quot; : &quot;2020-12-23&quot;
  }, {
  ...
  } ]
  </code></pre>
  <p>For each <code>join_id</code> I should do next things:</p>
  <ol>
  <li>Split string into key-values pairs:
  <code>utm_campaign, toyota; utm_content, multiformat_sites; etc</code></li>
  <li>Filter them (Java code below);</li>
  <li>Convert keys to another format; uses table from database (Java code below);</li>
  </ol>
  <p>My main goals is to repeat this Java code:</p>
  <pre><code>public class GaUtmFactoryService {
  
      private static final String INVALID_MACRO_FOOTPRINTS = &quot;^.*[{\\[%]+.+[}\\]%].*$&quot;;
  
      public Map&lt;String, String&gt; extractUtmMarks(String utmMarks) {
          if (utmMarks == null || utmMarks.isBlank()) {
              return Collections.emptyMap();
          }
          return Arrays.stream(utmMarks.split(&quot;\\s*&amp;\\s*&quot;))
                  .map(s -&gt; s.trim().split(&quot;\\s*=\\s*&quot;))
                  .filter(this::isUtmMarksValid)
                  .collect(Collectors.toMap(
                          key -&gt; convertCsUtmMarkToGa(key[0]),
                          value -&gt; value[1],
                          (val1, val2) -&gt; val2)
                  );
      }
  
      
      private boolean isUtmMarksValid(String[] utmMarks) {
          return utmMarks.length == 2
                  &amp;&amp; !convertCsUtmMarkToGa(utmMarks[0]).isBlank()
                  &amp;&amp; !utmMarks[1].isBlank()
                  &amp;&amp; Arrays.stream(utmMarks).noneMatch(this::isUtmMarkContainsInvalidChars);
      }
  
      private boolean isUtmMarkContainsInvalidChars(String utmMark) {
          return utmMark.matches(INVALID_MACRO_FOOTPRINTS)
                  || !StandardCharsets.US_ASCII.newEncoder().canEncode(utmMark);
      }
  
     
      private String convertCsUtmMarkToGa(String utmMark) {
         switch (utmMark) {
              case &quot;utm_medium&quot;:
                  return &quot;ga:medium&quot;;
              case &quot;utm_campaign&quot;:
                  return &quot;ga:campaign&quot;;
              case &quot;utm_source&quot;:
                  return &quot;ga:source&quot;;
              case &quot;utm_content&quot;:
                  return &quot;ga:adContent&quot;;
              case &quot;utm_term&quot;:
                  return &quot;ga:keyword&quot;;
              case &quot;utm_target&quot;:
              case &quot;utm_a&quot;:
                  return &quot;&quot;;
              default:
                  return rowUtmMarks;
          }
      }
  
  }
  </code></pre>
  <p>Usages from outside:</p>
  <pre><code>public Map&lt;String, String&gt; getConvertedMarks() {
          GaUtmFactoryService gaUtmFactoryService = new GaUtmFactoryService();
          String utmMarks = &quot;utm_campaign=toyota&amp;utm_content=multiformat_sites&amp;utm_medium=cpc&amp;utm_source=facebook&quot;;
          Map&lt;String, String&gt; converted = gaUtmFactoryService.extractUtmMarks(utmMarks);
          //should be:
          ////{ga:campaign=toyota, ga:adContent=multiformat_sites, ga:medium=cpc, ga:source=facebook}
          return converted;
      }
  </code></pre>
  <p>Is it even possible with NiFi? Or if it's hard, maybe should i just create REST microservice with some endpoints for this task?</p>
  <p><strong>UPDATE</strong></p>
  <p>I did <code>EvaluateJsonPath</code> and <code>SplitJson</code>. Now each json file have an attribute: <code>utm.marks = utm_campaign=toyota&amp;utm_content=multiformat_sites&amp;utm_medium=cpc&amp;utm_source=mytarget</code></p>
  <p>I need to split these attributes and get smth like this:</p>
  <p><code>campaign.key = ga:campaign</code></p>
  <p><code>campaign.value = toyota</code></p>
  <p><code>content.key = ga:content</code></p>
  <p><code>content.value = multiformat_sites</code></p>
  <p>etc.</p>