Прослушивание HTTP-потока Json запускает JSON: ParserError - PullRequest
0 голосов
/ 22 октября 2019

Мой проект Rails прослушивает поток HTTP типа text / json. Обычно он работает нормально примерно через час, а затем API, похоже, отправляет два объекта одновременно и вызывает JSON::ParserError, скорее всего, из-заAPI (я не контролирую его) отправляет два объекта JSON одновременно без запятой.

Я хотел бы знать, есть ли какая-то проверка (возможно, регулярное выражение?), которую я могу включить, чтобы убедиться, чтовсе входные строки, которые передаются в JSON.parse (), являются действительными объектами JSON без каких-либо проблем с производительностью. Я хотел бы передать каждый объект JSON, который API выдает в JSON.parse (), не пропуская его из-заAPI отправляет их не разделенными запятыми, если это возможно.

Мой код для задания rails, которое выполняет синтаксический анализ и сохраняет проанализированный объект json как объект ActiveRecord (имена переменных были изменены из оригиналов, и я мог бы иметьиспользовал рубиновые ключевые слова или что-то еще, поэтому я прошу прощения, если я запутал это.)

  def perform(*args)
    # Do something later
    puts "Listener Started!"

    response = HTTP.get("https://example.com/stream")
    response.body.each do |piece|
      parsed = piece && piece.length >= 2 ? JSON.parse(piece) : nil
      if parsed
        thing = Thing.find_or_create_by(id: parsed["uuid"]) do |thing|
          thing.content = parsed["content"]
          thing.created_at = parsed["created_at"]
          thing.amount = parsed["amount"]
          thing.variety = parsed["variety"]
        end
        expense.employee = Author.find_or_create_by(id: parsed["author"]["uuid"]) do |author|
          author.first_name = parsed["author"]["first_name"]
          author.last_name = parsed["author"]["last_name"]
        end
        thing.save
      end
    end
  end

Это ошибка, которую я 'м получения:

Error performing ListenForExpenseJob (Job ID: 4b275dc3-4234-4249-8dc5-186ac02fc424) from Async(default) in 2826495.7ms:

JSON::ParserError (784: unexpected token at 
'{"uuid": "ea065b39-68d7-4abb-bb44-04f3006ad2bb", "content": "Impedit aut amet ea quisquam culpa saepe.", "created_at": "2019-10-13T02:16:53", "amount": 654, "variety": "OMR", "author": {"uuid": "910e81b1-afd1-4a04-9fc5-ff644abc5a96", "first_name": "Jenny", "last_name": "Person"}}
{"uuid": "f2981a04-4699-476e-86ed-d83999428045", "description": "Debitis libero voluptas quidem deleniti facilis.", "created_at": "2019-10-05T22:17:09", "amount": 6381, "variety": "BRL", "author": {"uuid": "a73e2de8-abf2-4e99-8e3b-e3fb72d0b3ba", "first_name": "Jacob", "last_name": "Human"}}
'):

1 Ответ

0 голосов
/ 22 октября 2019

Если неправильно сформированные записи всегда точно , как вы описали здесь, тогда простое, если наивное решение может быть:

piece = <<EOF
{"uuid": "ea065b39-68d7-4abb-bb44-04f3006ad2bb", "content": "Impedit aut amet ea quisquam culpa saepe.", "created_at": "2019-10-13T02:16:53", "amount": 654, "variety": "OMR", "author": {"uuid": "910e81b1-afd1-4a04-9fc5-ff644abc5a96", "first_name": "Jenny", "last_name": "Person"}}
{"uuid": "f2981a04-4699-476e-86ed-d83999428045", "description": "Debitis libero voluptas quidem deleniti facilis.", "created_at": "2019-10-05T22:17:09", "amount": 6381, "variety": "BRL", "author": {"uuid": "a73e2de8-abf2-4e99-8e3b-e3fb72d0b3ba", "first_name": "Jacob", "last_name": "Human"}}
EOF

piece = piece.gsub("\n", '').gsub(/}{/, '},{').prepend('[').concat(']')
parsed = JSON.parse(piece)
parsed.each do |parsed_piece|
  # do something to validate and save parsed piece
end

Это будет работать для любого количества записей, которыепосылать сразу, удаляя символы новой строки, разделяя записи запятыми, превращая всю строку в массив JSON, анализируя массив JSON, а затем перебирая элементы массива.

Возможно, вы умнете.split() или .scan() для поиска }{ и разбиения строки на массив, основанный на этом элементе, затем выполните JSON.parse для каждого элемента массива и , затем выполните итерацию по массивудля проверки и сохранения, например:

pieces = piece.gsub("\n", '').split(/(}{)/)
new_pieces = []
pieces.each_with_index do |piece, index|
  if pieces.length == 1
    new_pieces << piece
  elsif index.zero?
    new_pieces << "#{piece}#{pieces[index + 1][0]}"
  elsif index.even?
    new_piece = "#{pieces[index - 1][1]}#{piece}"
    new_piece = "#{new_piece}#{pieces[index - 1][0]}" unless index == pieces.length - 1
    new_pieces << new_piece
  end
end
new_pieces.map { |piece| JSON.parse(piece) }

И вы, вероятно, можете сделать этот блок немного проще с некоторыми из вышеупомянутых умностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...