Как отследить ошибки анализа с помощью Aeson? [+ Ответить]

У меня есть большие ( > 1Mb), простые JSON файлы для синтаксического анализа. Я использовал Aeson, следуя руководству fpcomplete в своей школе Haskell (спасибо вам, ребята, кстати).

Поскольку некоторые файлы (и не все) терпят неудачу, я подозреваю, что json файл не должен уважать структуру, которую я ожидаю. Сообщения об ошибках, которые я получил до сих пор, были

> Failed reading: satisfy

Мой вопрос:

  • "Как я могу получить более подробную информацию о том, что пошло не так?"

Два уровня отладки/ведения журнала/трассировки составляют мои цели:

  • идентификатор анализатора, то есть какой тип данных не может быть проанализирован (например, для Parsec)
  • идентификация данных с помощью строки / char номер

Ответ 1

Существует решение: aeson-better-errors - это хороший учебник одноименного пакета Гарри Гарродом. Этот пакет оказался прост в использовании и предоставил самую необходимую мне информацию.

Одно замечание: этот пакет не будет решать структурные ошибки, например, отсутствие фигурной скобки. Для таких ошибок вы по-прежнему получаете сообщения InvalidJSON, которые не локализованы во входном потоке.

Ответ 2

К сожалению, Aeson торгует хорошими сообщениями об ошибках для скорости. Тем не менее, вы можете делать многофазные декодирования, пока ваша структура JSON хороша, и файл не выполняет вашу схему, а не анализирует как JSON вообще.

Многофазным я подразумеваю декодировать части структуры за раз. Вы также можете собрать отказоустойчивые значения, чтобы определить, почему они не выполняли ваш синтаксический анализ.

parse :: FromJSON a => ByteString -> Maybe [Either Value a]
parse s = case decode s of
  Nothing -> fail "could not decode as array"
  Just values -> map tryDecode values
where
  tryDecode :: FromJSON a =>Value -> Either Value a
  tryDecode v = case decode (encode v) of
    Nothing -> Left v
    Just a -> Right a

Бит decode . encode довольно неэффективен, поскольку он проходит через ByteString, но его можно улучшить с помощью более простых парсеров Aeson.