Вопросы о выводе результатов в JSON являются довольно частыми среди всех обращений в Техническую поддержку. Поэтому мы подготовили небольшой обзор всех возможных способов это сделать.
В качестве "подопытного" возьмем парсер Google подсказок SE::Google::Suggest. Также для большей наглядности условимся что в результате нам необходимы сам запрос, кол-во подсказок по нему, непосредственно сами подсказки и количество символов в каждой подсказке (ее длина).
1. Вывод в JSON для одиночных запросов
Простейший вариант вывода в JSON - это использование метода шаблонизатора .json:
Здесь мы в Общем формате результата создаем пустой объект obj, записываем в него две переменные (запрос query и кол-во результатов по нему count) и пустой массив suggests. После чего наполняем массив объектами, содержащими подсказку keyword и кол-во символов в ней length. Тем самым получается нужная структура. И выводим это все в виде JSON строки:Код:[% obj = {}; obj.query = query; obj.count = p1.totalcount; obj.suggests = []; FOREACH item IN p1.results; obj.suggests.push({ keyword = item.suggest length = item.suggest.length }); END; obj.json %]
Этот способ отлично подходит для одиночных запросов, например через API метод oneRequest.Код:{"suggests":[{"keyword":"testzentrum","length":11},{"keyword":"teste dich","length":10},{"keyword":"testosterone","length":12},{"keyword":"testzentrum in der nähe","length":23},{"keyword":"testosteron","length":11},{"keyword":"testdaf","length":7},{"keyword":"test center near me","length":19},{"keyword":"testament","length":9}],"count":8,"query":"test"}
2. Формирование JSON построчно
Но что будет, если в предыдущем случае подать на вход несколько запросов? Проверим, добавив для удобства перевод строки после вывода JSON. И попробуем поработать с полученным JSON'ом, вставив его в любой редактор JSON:
Как видно на скриншоте, мы получили ошибку, т.к. JSON не валиден. Сейчас это по сути набор строк, который не отвечает правилам JSON.
Самым очевидным решением по формированию валидного JSON'а для нескольких запросов (да и в целом для любого количества больше одного) является использование массива. Если посмотреть на любой массив в JSON, то он похож на строки, разделенные запятыми. И все это взято в квадратные скобки. Что ж, добавим к выводу запятые (вместе с переводом строки, в формате результата) и квадратные скобки в самом начале и конце (воспользуемся для этого функционалом Начального и Конечного текстов).
Код шаблона в Формате результата по сути остается такой же, как и предыдущем примере, только добавляется запятая после каждой строки (и перевод строки для удобства):
Начальный и Конечный тексты:Код:obj.json _ ",\n"
Получаем такой результат:
Как видим, снова ошибка
Если изучить то, что получилось - становится понятно, что все портит запятая в самом конце (на скрине выделена стрелкой). Но она выводится вместе со строкой JSON'а и нет возможности указать парсеру что какая-то строка последняя и запятую выводить не нужно...
Вполне неплохим решением в этой ситуации будет добавление пустого объекта в самый конец. Для этого просто пропишем его в Конечном тексте.
Теперь, если запустить пресет, получим валидный JSON в виде массива объектов, где каждый объект - это данные по каждому запросу.
При дальнейшей обработке пустой объект можно просто игнорировать.
2.1. Избавляемся от пустого обьекта
Но как быть, если по какой-то причине пустой объект в конце недопустим? Существует небольшой лайфхак. Надо немного изменить логику построчного формирования и выводить запятую не в конце каждой строки, а в начале. И нужно завести переменную, которая будет играть роль флага, указывающего ставить ли запятую или нет. В примере ниже это переменная notFirst.
Итого шаблон для Формата результата будет выглядеть так:
Не забудьте убрать пустой объект из Конечного текста.Код:[% IF notFirst; ",\n"; ELSE; notFirst = 1; END; obj = {}; obj.query = query; obj.count = p1.totalcount; obj.suggests = []; FOREACH item IN p1.results; obj.suggests.push({ keyword = item.suggest length = item.suggest.length }); END; obj.json %]
В результате получаем валидный JSON без пустых объектов.
Данный метод не имеет никаких ограничений по кол-ву запросов и объёму результатов. Его вполне можно использовать для любых задач, требующих вывод в JSON.
Но существует еще один способ и о нем ниже.
3. Формирование объекта в памяти и вывод результатов в JSON в конце работы задания
Выше мы для нескольких запросов выводили данные в массив. Но как быть, если по какой-то причине массив нам не подходит и нужен один большой объект? И чтобы ключами в этом объекте были подаваемые на вход запросы...
Решение есть. Нужно создать в самом начале работы задания пустой объект, писать в него данные по ходу парсинга и в конце работы задания вывести все это в результат. Поможет все это реализовать опять же функционал Начального и Конечного текстов. Как известно, Начальный отрабатывает в самом начале работы задания, а Конечный - в конце. Этим и воспользуемся.
Итак, в Начальном тексте пропишем создание пустого объекта (используя шаблонизатор):
В Общем формате результата пропишем запись в этот объект:Код:[% obj = {} %]
И в Конечном тексте пропишем вывод в JSON:Код:[% obj.${query} = {}; obj.${query}.count = p1.totalcount; obj.${query}.suggests = []; FOREACH item IN p1.results; obj.${query}.suggests.push({ keyword = item.suggest length = item.suggest.length }); END %]
Запускаем и получаем JSON в требуемом виде:Код:[% obj.json %]
Благодаря хранению данных в памяти, можно дополнительно перед выводом в результат произвести с ними различные действия. К примеру отсортировать или произвести подсчет какой-то статистики. Кроме этого данный метод более удобен для логического понимания его работы, в отличие от вышеописанного построчного вывода, который является несколько нетипичным вариантом формирования JSON. Но у этого варианта есть один существенный минус. Его нельзя использовать для очень больших объёмов запросов, т.к. из-за хранения всех данных в памяти можно попросту упереться в ее нехватку. Также итоговый вывод или пост-обработка собранных результатов на большом количестве запросов может занять много времени и привести к ошибкам в работе А-Парсера.Код:eJxtVN9v2jAQ/lcii0qtVEWt2r1k2gNlsHVi0EL7BDx45JIaHDuzHboqyv++OwcS QnmxfHff/fjuzi6Z43ZrnwxYcJZFi5Ll/s4iFkPCC+nYNcu5sWDIvGDzYRT90DqV EEXzIk3BEuKAXa2uGfrj1Y60yTjFWVwE+s8m7JV/CzAfVfAtKKuvS3WsC9e6UA4t +W3otOPSy6cgW6eziFus0LhUo+ls2B/8DISDLHickPs+O5ndWe8wL+zbZUn2pdvC x7s2MUakEAdMbZOgUvd2YgprLSGqK0wynHwPLlasYT3nO3jRyDoRElr1CKUJzwAN vZg7IGuY+A5dXoXuH/WQx7FwQisu69ZRv9t2viqBRNBfacQSJwF2ZHSGKgc+gCd6 aPuC9bzMMEThfZ9rHxYlXFq4ZhZLHXEsJD61IGHDnTbTnOpBfcm06ks5hh3IFubj PxRCxrgc/QSdHveO5yHTTzGqht5xqh2Yd4M1NFG89DD93XrFeqzTQzOkyIRD2Q5o a1B7g8otQN70bEKwTBto0jhTQJMc1z8HFTe76le0M9Z+3gGEG6tVDegw7Eysq1xr lYh0ityMiOGALNQLvr+pGugsl0CUVSElTszCrN2cvt1PiISmK5+cBz5F5+U6raX9 NUcdPWMjcDO/UIEZNvk46z7kmkv5OhsfW1i7bX7T6HXU/wG+geLm/i7xJ/jz7uh+ 708axRoXPtW4isi5WjXfSfPplGc/laiscNAb+1SjiTphUYc9tDhFFt1W/wG6160c
В этой статье мы рассмотрели все варианты вывода результатов в JSON. Какой использовать - зависит от решаемых задач. Оптимальным является построчный вывод, но если нужно сделать какую-то пост-обработку собранных результатов "на лету" - то лучше использовать 3-й метод.
-
Вступайте в наш Telegram чат: https://t.me/a_parser Нас уже 2600+ и мы растем!Скрыть объявление
Обзор вариантов вывода результатов в JSON виде
Полный обзор существующих способов вывода результатов в JSON
Метки: