Я пытаюсь глотать текстовые данные из локального каталога в HDFS, перед тем как проглатывать, мне нужно преобразовать текст в действительный json. Для этого я использую процессор JavaScript Evaluator.
В javascript-оценщике я не могу прочитать какую-либо запись.
Вот мой пример кода:
for(var i = 0; i < records.length; i++) {
try {
output.write(records[i]);
} catch (e) {
error.write(records[i], e);
}
}
Есть ли другой лучший вариант, кроме JavaScript-оценщика?
Вот мои исходные данные:
{
1046=
1047=
1048=5324800
1049=20180508194648
1095=2297093400,
1111=up_default
1118=01414011002101251
1139=1
}
{
1140=1
1176=mdlhggsn01_1.mpt.com;3734773893;2472;58907
1183=4
1211=07486390
1214=0
1227=51200
1228=111
1229=0
1250=614400,
}
ОБНОВИТЬ:
Как ответ @metadaddy, я пытаюсь использовать Groovy insted JavaScript. Я получаю следующее исключение для тех же данных, которые @metadaddy показал в своем ответе.
Вот скриншот моей ошибки.
Скрипт Groovy в сборщике данных StreamSets выполняется намного быстрее, чем JavaScript, так что вот то же решение в Groovy.
Используя текстовый формат, начало каталога создаст запись с /text
полем для каждой строки ввода.
Этот скрипт будет создавать необходимую структуру записи:
for (i = 0; i < records.size(); i++) {
try {
// Start of new input record
if (records[i].value['text'].trim() == "{") {
// Use starting input record as output record
// Save in state so it persists across batches
state['outRecord'] = records[i]
// Clean out the value
state['outRecord'].value = [:]
// Move to next line
i++
// Read values to end of input record
while (i < records.size() && records[i].value['text'].trim() != "}") {
// Split the input line on '='
def kv = records[i].value['text'].trim().split('=')
// Check that there is something after the '='
if (kv.length == 2) {
state['outRecord'].value[kv[0]] = kv[1]
} else if (kv[0].length() > 0) {
state['outRecord'].value[kv[0]] = NULL_STRING
}
// Move to next line of input
i++
}
// Did we hit the '}' before the end of the batch?
if (i < records.size()) {
// Write record to processor output
output.write(state['outRecord'])
log.debug('Wrote a record with {} fields',
state['outRecord'].value.size());
state['outRecord'] = null;
}
}
} catch (e) {
// Write a record to the error pipeline
log.error(e.toString(), e)
error.write(records[i], e.toString())
}
}
Выполнение этого на входных данных:
{
1=959450992837
2=95973085229
3=1525785953
4=29
7=2
8=
9=
16=abd
20=def
21=ghi;jkl
[email protected]
23=1525785953
40=95973085229
41=959450992837
42=0
43=0
44=0
45=0
74=1
96=1
98=4
99=3
}
Дает выход:
{
"1": "959450992837",
"2": "95973085229",
"3": "1525785953",
"4": "29",
"7": "2",
"8": null,
"9": null,
"16": "abd",
"20": "def",
"21": "ghi;jkl",
"22": "[email protected]",
"23": "1525785953",
"40": "95973085229",
"41": "959450992837",
"42": "0",
"43": "0",
"44": "0",
"45": "0",
"74": "1",
"96": "1",
"98": "4",
"99": "3"
}
Ваш JavaScript должен читать входные данные, создавая выходные записи.
Используя текстовый формат, начало каталога создаст запись с /text
полем для каждой строки ввода.
Этот JavaScript построит необходимую структуру записи:
for(var i = 0; i < records.length; i++) {
try {
// Start of new input record
if (records[i].value.text.trim() === '{') {
// Use starting input record as output record
// Save in state so it persists across batches
state.outRecord = records[i];
// Clean out the value
state.outRecord.value = {};
// Move to next line
i++;
// Read values to end of input record
while (i < records.length && records[i].value.text.trim() !== '}') {
// Split the input line on '='
var kv = records[i].value.text.trim().split('=');
// Check that there is something after the '='
if (kv[1].length > 0) {
state.outRecord.value[kv[0]] = kv[1];
} else if (kv[0].length > 0) {
state.outRecord.value[kv[0]] = NULL_STRING;
}
// Move to next line of input
i++;
}
// Did we hit the '}' before the end of the batch?
if (i < records.length) {
// Write record to processor output
output.write(state.outRecord);
log.debug('Wrote a record with {} fields',
Object.keys(state.outRecord.value).length);
state.outRecord = null;
}
}
} catch (e) {
// Send record to error
log.error('Error in script: {}', e);
error.write(records[i], e);
}
}
Вот предварительный просмотр преобразования на ваших входных данных образца:
Теперь, чтобы записать всю запись в HDFS как JSON, просто установите формат данных в назначении назначения Hadoop FS JSON.
{"1":1234,"2":6788,"3":56778}
- это верно?
i < records.size()
в условие цикла while - это должно отловить отсутствующую закрывающую скобку.