#python #apache-nifi
Вопрос:
Я конвертирую полезную нагрузку JSON в XML-файл с помощью процессора Python executeScript в NiFi. JSON выглядит так :
{
"Header": {
"Att1": 1,
"Att2": "value2",
"Att3": "1",
"Att4": "경기00자123"
}
}
Скрипт python для преобразования этого JSON в XML выглядит следующим образом :
import json
import xml.etree.ElementTree as ET
import java.io
from org.apache.commons.io import IOUtils
from java.nio.charset import StandardCharsets
from org.apache.nifi.processor.io import StreamCallback
class ModJSON(StreamCallback):
def __init__(self):
pass
def process(self, inputStream, outputStream):
text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
data = json.loads(text)
root = ET.Element("headerinfo")
entity = ET.SubElement(root, "headerfile")
ET.SubElement(entity, "Att1").text = str(data["Header"]["Att1"])
ET.SubElement(entity, "Att2").text = str(data["Header"]["Att2"])
ET.SubElement(entity, "Att3").text = str(data["Header"]["Att3"])
ET.SubElement(entity, "Att4").text = data["Header"]["Att4"].encode("utf8")
xmlNew = ET.tostring(root)
outputStream.write(bytearray(xmlNew))
flowFile = session.get()
if flowFile != None:
try :
flowFile = session.write(flowFile, ModJSON())
flowFile = session.putAttribute(flowFile, "filename", 'headerfile.xml')
session.transfer(flowFile, REL_SUCCESS)
session.commit()
except Exception as e:
flowFile = session.putAttribute(flowFile,'python_error', str(e))
session.transfer(flowFile, REL_FAILURE)
Независимо от того, как я пытаюсь закодировать Att4 японскими символами, в результирующем XML это выглядит примерно так :
amp;#228;amp;#186;amp;#172;amp;#233;amp;#131;amp;#189;111amp;#227;amp;#130;amp;#146;3
Как я могу изменить код, чтобы исправить это?
Перепробовал много разных вещей, но, похоже, ничего не работает.
Комментарии:
1. Попробуйте аргументы ElementTree.tostring .. он поддерживает кодировку и режим.
2. @daggett Спасибо за предложение! Попробовал и получил эту ошибку — «write(): 1-й аргумент не может быть преобразован в байт[], int»
3. попробуйте написать(xmlNew.encode(‘utf-8’)) или любую другую кодировку, которую вы использовали для xml.tostring
4. Спасибо за ваши комментарии @daggett Попробовал то, что вы упомянули, это не выдает ошибку, но данные все равно выглядят так :
amp;#20140;amp;#37117;111amp;#12434;3
Ответ №1:
похоже, в jython есть проблема со строками байтов-они автоматически преобразуются в объект str с неправильной кодировкой.
однако у ElementTree есть функция записи, которая может записывать в файлоподобный объект, а OutputStream (объект java) фактически реализует функцию записи-таким образом, мы могли бы заставить ElementTree записывать непосредственно в OutputStream
import json
import xml.etree.ElementTree as ET
from org.apache.commons.io import IOUtils
from java.nio.charset import StandardCharsets
from org.apache.nifi.processor.io import StreamCallback
class ModJSON(StreamCallback):
def process(self, inputStream, outputStream):
text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
data = json.loads(text)
root = ET.Element("headerinfo")
entity = ET.SubElement(root, "headerfile")
ET.SubElement(entity, "Att1").text = str(data["Header"]["Att1"])
ET.SubElement(entity, "Att2").text = str(data["Header"]["Att2"])
ET.SubElement(entity, "Att3").text = str(data["Header"]["Att3"])
ET.SubElement(entity, "Att4").text = data["Header"]["Att4"]
ET.ElementTree(root).write(outputStream, encoding='utf-8')
flowFile = session.get()
if flowFile != None:
try :
flowFile = session.write(flowFile, ModJSON())
flowFile = session.putAttribute(flowFile, "filename", 'headerfile.xml')
session.transfer(flowFile, REL_SUCCESS)
session.commit()
except Exception as e:
flowFile = session.putAttribute(flowFile,'python_error', str(e))
session.transfer(flowFile, REL_FAILURE)
Комментарии:
1. Да, это работает! Большое спасибо @dagget