NiFi — Преобразование строки JSON в допустимый JSON

#json #apache-nifi #jolt

#json #apache-nifi #jolt

Вопрос:

Используя updateRecord, я пытаюсь преобразовать строку json в допустимый json:

Входные данные:

 {
  "user" : "{"id":"1","name":"TEST"}"
}
 

Текущий вывод:

 {
  "user":"{id=1, name=TEST}"
}
 

Ожидаемый результат:

 {
  "user": { 
      "id": "1", 
      "name": "TEST" 
  }
}
 

Как я могу это исправить? Использовать другой процессор или скрипт? Можете ли вы дать мне совет?

С уважением!

updateRecord:

введите описание изображения здесь

Ответ №1:

Вы можете использовать JoltTransformJSON processsor ( библиотека преобразования Jolt предназначена для преобразования JSON в другой JSON) со спецификацией

 [
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "u": "=split('"', @(1,user))",
      "user": "=join('',@(1,u))"
    }
  },
  {
    "operation": "remove",
    "spec": {
      "u": ""
    }
  }
]
 

где " фрагменты удаляются с помощью split, а затем функция join используется для объединения остальной части строки. Лишний созданный вспомогательный атрибут u удаляется на последнем шаге.

введите описание изображения здесь

Редактировать: в зависимости от вашего редактирования используйте следующие преобразования

 [
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "user": "=split('"', @(1,user))",
      "id": "@(1,user[3])",
      "name": "@(1,user[7])"
    }
  },
  {
    "operation": "remove",
    "spec": {
      "user": ""
    }
  },
  {
    "operation": "shift",
    "spec": {
      "@": "user"
    }
  }
]
 

введите описание изображения здесь

Комментарии:

1. Спасибо, но это не ожидаемый результат. Я только что обновил вопрос.

2. Добро пожаловать, @JorgeAires, я отредактировал.

3. Сработало как шарм! Я оценил.

Ответ №2:

Причина, по которой updateRecord работает таким образом, заключается в том, что он выводит схему записи из входных записей и определяет, что существует пользователь поля с типом String .

Таким образом, даже если вы попытаетесь использовать ScriptedTransformRecord вместо updateRecord и попытаетесь использовать Record.setValue(fieldName,convertStringToMap(previousValue)) , это преобразует карту в строку, и вы все равно получите поле user со строковым типом. (setValue() не изменяет тип уже существующих полей)

Обходным путем может быть обогащение записи добавлением нового поля, скажем, user_map с типом Map(строка, строка).

В качестве альтернативы, просто создайте новую запись с новой схемой, используя ScriptedTransformRecord, например, используя следующий сценарий groovy, где JsonSlurper используется для отмены экранирования Json

 import groovy.json.JsonSlurper
import org.apache.nifi.serialization.SimpleRecordSchema
import org.apache.nifi.serialization.record.MapRecord
import org.apache.nifi.serialization.record.Record

def slurper = new JsonSlurper()
Record result = new MapRecord(new SimpleRecordSchema([]),[:]) // empty record
record.toMap().each { k,v ->
    result.setValue(k,slurper.parseText(v as String)) // adding a field Map<String,String>
}
return result