Pull to refresh

Потоковый JSON-парсер YAJL

Reading time 2 min
Views 13K
В связи, с возникшей недавно потребностью работе с данными в JSON-формате, решил исследовать вопрос о существующих библиотеках для работы с JSON для С/С++.Сразу хочу оговориться, что детального рассмотрения всего множества библиотек для работы c JSON я представлять не собирался. На текущий момент их существует более-менее большое кол-во. Вот список с сайта json.org (http://www.json.org):
  • C:
    • JSON_checker
    • JSON parser
    • json-c
    • M's JSON parser
    • YAJL
    • cJSON
    • Jansson
    • js0n
    • LibU
  • C++:
    • jsoncpp
    • zoolib
    • JOST
    • CAJUN
    • libJSON
    • nosjob
Основные требования, которые я выдвигал для искомой библиотеки:
  • Малое потребление памяти (большинство JSON-парсеров, как и XML парсеров, производят разбор файла в какие-то свои структуры в памяти, из которых можно извлекать информацию о данных в файле (а ля DOM-дерево для XML). Суть в том, что зависимость размера памяти под эти объекты линейна от самого файла и при получении файла, размеры которого превышают ожидаемые размеры, мы получаем неожидаемые росты памяти (и время на выделение/освобождение), а может так случиться, что памяти в таком кол-ве может и не быть).
  • Возможность частичного парсинга данных (т.е. если я уже прочитал необходимые данные, зачем мне парсить всё остальное? Например, прочитал я заголовок сообщения и всё, хватит.)
  • Отсутствие лишних «наворотов» (типа поиск с использованием специлизированных запросов или валидация – ограничимся просто парсингом).
Вначале я рассматривал cJSON (http://sourceforge.net/projects/cjson), но оказалось, что он парсит весь документ в память (хотя делает это с минимальным её потреблением и достаточно быстро). В итоге я остановился на yajl (http://lloyd.github.com/yajl) – надо сказать единственном потоковый парсер JSON.Некоторые факты о yajl:
  • Он производит парсинг в стиле SAX – разработчик создаёт методы-обработчики для конкретных типов событий (начало объекта, встреча ключа, встреча текстового значения, встреча числового значения и т.д.) и передаёт их список в парсер, потом запускает парсер и парсер в процессе парсинга вызывает эти методы с данными, которые он встретит в файле (можно выбирать по каким событиям получать уведомления, а по каким нет).
  • Он позволяет выполнять потоковый парсинг – данные можно передавать в парсинг частями (по мере получения по сети, генерации другим кодом или чтения с диска).
  • Парсинг можно прервать в процессе разбора.
  • Потребление памяти – минимально (проверено на опыте: используется лишь необходимый минимум, которые не зависит от размера данных для парсинга).
  • Скорость на уровне (за счёт минимума выполняемых проверок – лишь well-form валидация).
  • Возможность генерации JSON (выполняется примерно такими же методами, что получение уведомлений о событиях).
  • Документация по парсеру достаточна скудна, но пара примеров на сайте и изучение комментариев в заголовочных файлах позволят всё понять о том, как работать с данной библиотекой.
И пара слов в заключение:
  • Для моих нужд библиотека подошла, я даже научился использовать её в C++ классах, несмотря на то, что она использует ссылки на функции (function pointers).
  • Но кромер «push»-парсера, хотелось бы узнать: существуют ли «pull»-парсеры (а ля StAX или интерфейс «reader» в libxml-2) для JSON?
Tags:
Hubs:
+14
Comments 21
Comments Comments 21

Articles