StreamSets конвертирует текст в Json

1

Я пытаюсь глотать текстовые данные из локального каталога в 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 показал в своем ответе.

Вот скриншот моей ошибки. Изображение 174551

Теги:
pipeline

2 ответа

1

Скрипт 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"
}
  • 0
    Здравствуйте @metadaddy, я обновил свой вопрос с недавним исключением. пожалуйста, посмотрите.
  • 0
    Я добавил проверку i < records.size() в условие цикла while - это должно отловить отсутствующую закрывающую скобку.
Показать ещё 4 комментария
1

Ваш 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);
  }
}

Вот предварительный просмотр преобразования на ваших входных данных образца:

Изображение 174551

Теперь, чтобы записать всю запись в HDFS как JSON, просто установите формат данных в назначении назначения Hadoop FS JSON.

  • 0
    Спасибо за ответ. мои данные не в формате JSON. Мне нужно преобразовать это в действительный формат JSON. Для этого я использую Javascript Ecaluator.
  • 0
    Просто чтобы уточнить - вы читаете данные в текстовом формате, который выглядит как пример, который вы предоставили, и вы хотите, чтобы выходной JSON выглядел как {"1":1234,"2":6788,"3":56778} - это верно?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню