• 0
Akad

Нужен нормальный JSON парсер

Вопросы

Кто поделится нормальным JSON парсером? Источник JSON - команда на php

json_encode(unserialize($value));

То есть это просто сереализованная структура данных, которая изначально не известна (точнее их куча разных), и которую надо распарсить определённым алгоритмом. Стандартный - System.JSON - вообще хрень полная. Ничего не умеет, даже квадратные скобки если и парсит, то криво. С гитхаба есть

https://github.com/thomaserlang/delphi-json  - так же штука мало что умеющая, и

https://github.com/tmcdos/tiny-json -это почти то, что надо. Но они слишком заморочились с хешами и вкрался каской-то глюк. На некоторых входных данных json1.Child[0] = nil, хотя json1.Count > 0. Искать проблему в этом коде нет ни какого желания, слишком всё усложнено.

В общем кто чем пользуется?


 

Изменено пользователем Akad

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 ответов на этот вопрос

  • 0

Нашёл SuperObject, он из ~1500 JSON проглючил всего на 4-х. Хотя online парсеры эти 4 кушают без проблем. Уже результат. Но всё же хочется лучше. Не думал, что парсинг структурированного текста хоть как-то сложная задача...
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

тут все пользуются XSuperObject

можно пример, чего такого он у вас не разобрал?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

А меня System.JSON полностью устраивает. Ошибок парсинга валидных данных не было ни разу, скорость на нормальном уровне. Гигабайтные данные правда не парсирую, но мне это и не нужно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
13 часа назад, krapotkin сказал:

можно пример, чего такого он у вас не разобрал?

Сейчас с ходу что он не распарсил не прилетело, но вот распарсил криво:

{"0":{"PRODUCT_ID":"808","OPTIONS":null,"AMOUNT":1,"SECTION_ID":"35"},"additional_849":{"AMOUNT":3,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":849,"ID":"additional_849","PRODUCT_ID":"additional_849"},"additional_850":{"AMOUNT":"2","TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":850,"ID":"additional_850","PRODUCT_ID":"additional_850"},"additional_851":{"AMOUNT":2,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":851,"ID":"additional_851","PRODUCT_ID":"additional_851"},"additional_852":{"AMOUNT":2,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":852,"ID":"additional_852","PRODUCT_ID":"additional_852"}}



Obj := SO(s); 
Assert(obj.AsArray <> nil); 

Сработал assert, хотя root - это массив.

2 часа назад, Tumaso сказал:

А меня System.JSON полностью устраивает. Ошибок парсинга валидных данных не было ни разу, скорость на нормальном уровне.

Основная проблема стандартной библиотеки - это кривость работы с массивами [], и постоянные ассерты, когда нет элемента. Ну и общая громоздкость кода парсинга. То есть если структура JSON изначально известна и "стандартна", то проблем не будет. А если шаг влево, шаг вправо, то...

 

Изменено пользователем Akad

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 1
6 часов назад, Akad сказал:

Сейчас с ходу что он не распарсил не прилетело, но вот распарсил криво:

{"0":{"PRODUCT_ID":"808","OPTIONS":null,"AMOUNT":1,"SECTION_ID":"35"},"additional_849":{"AMOUNT":3,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":849,"ID":"additional_849","PRODUCT_ID":"additional_849"},"additional_850":{"AMOUNT":"2","TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":850,"ID":"additional_850","PRODUCT_ID":"additional_850"},"additional_851":{"AMOUNT":2,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":851,"ID":"additional_851","PRODUCT_ID":"additional_851"},"additional_852":{"AMOUNT":2,"TYPE":"additional","IS_ADDITIONAL":true,"ADDITIONAL_ID":852,"ID":"additional_852","PRODUCT_ID":"additional_852"}}


Obj := SO(s); 
Assert(obj.AsArray <> nil); 

Сработал assert, хотя root - это массив.

Основная проблема стандартной библиотеки - это кривость работы с массивами [], и постоянные ассерты, когда нет элемента. Ну и общая громоздкость кода парсинга. То есть если структура JSON изначально известна и "стандартна", то проблем не будет. А если шаг влево, шаг вправо, то...

 

правильно сработал, это не массив а объект. смотрите внимательно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
29 минут назад, Равиль Зарипов (ZuBy) сказал:

правильно сработал, это не массив а объект. смотрите внимательно

Брр. Почему не массив? Это массив элементов "0", "additional_849", "additional_851" и так далее. Они все находятся на одном уровне ведь. И выше них уровня нет.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 1

нуу, давайте так...

массив - [], объект - {}

или даже так 

image.png.c29572ffe9360b0e5a12660eb7056a77.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Изначально была такая структура:





a:5:{i:0;a:4:{s:10:"PRODUCT_ID";s:3:"808";s:7:"OPTIONS";N;s:6:"AMOUNT";i:1;s:10:"SECTION_ID";s:2:"35";}
s:14:"additional_849";a:6:{s:6:"AMOUNT";d:3;s:4:"TYPE";s:10:"additional";s:13:"IS_ADDITIONAL";b:1;s:13:"ADDITIONAL_ID";i:849;s:2:"ID";s:14:"additional_849";s:10:"PRODUCT_ID";s:14:"additional_849";}
s:14:"additional_850";a:6:{s:6:"AMOUNT";s:1:"2";s:4:"TYPE";s:10:"additional";s:13:"IS_ADDITIONAL";b:1;s:13:"ADDITIONAL_ID";i:850;s:2:"ID";s:14:"additional_850";s:10:"PRODUCT_ID";s:14:"additional_850";}
s:14:"additional_851";a:6:{s:6:"AMOUNT";d:2;s:4:"TYPE";s:10:"additional";s:13:"IS_ADDITIONAL";b:1;s:13:"ADDITIONAL_ID";i:851;s:2:"ID";s:14:"additional_851";s:10:"PRODUCT_ID";s:14:"additional_851";}
s:14:"additional_852";a:6:{s:6:"AMOUNT";d:2;s:4:"TYPE";s:10:"additional";s:13:"IS_ADDITIONAL";b:1;s:13:"ADDITIONAL_ID";i:852;s:2:"ID";s:14:"additional_852";s:10:"PRODUCT_ID";s:14:"additional_852";}}

Т.е. массив из 5 элементов ключ-значение. Так как есть ключ, то в JSON скобки {}. Всё корректно вроде. В смысле php часть отработала правильно.

Да и вообще говоря любой JSON на одном уровне - это массив ключ-значение (причём ключа может не быть). Вот и нужен парсер, который это понимает, а не занимается фантазированием.


 

Изменено пользователем Akad

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

если вашу мысль развить, то с т.з. php {"A":"B", "C":""D"} это тоже массив, но это не так

JSON это стандарт. Там написано, как выглядит массив, а как - нет. Несмотря на то, что вам может что-то казаться или не нравиться.

Изменено пользователем krapotkin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
2 часа назад, krapotkin сказал:

если вашу мысль развить, то с т.з. php {"A":"B", "C":""D"} это тоже массив, но это не так

JSON это стандарт. Там написано, как выглядит массив, а как - нет. Несмотря на то, что вам может что-то казаться или не нравиться.

Был-то массив. И в JSON представить данный массив по другому нельзя. Короче вопрос не в философии, а в том, что заранее не известны ни ключи ни значения, ни скобки. Надо JSON пропарсить. Чем?

У SuperObject - obj.AsObject так же глючен. Когда [] - у него nil, а мне случайным образом поступает то [], то {}, хотя внутри всегда массив заказов. Писать 100500 ветвлений копипастя один и тот-же код из-за того, что кому-то лень прописать в одном классе все скобки - бред. Неужели нет полноценного, не глючного JSON парсера для Delphi? Крайне не люблю велосипеды изобретать.

 

Изменено пользователем Akad

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

XSO буксует только в одном случае - если весь текст представляет собой массив

например

[12,34,56]

но это легко проверяется.

все остальное абсолютно нормально ложится.

если у вас на входе то массив, то объект, вам все равно придется работать с ними по разному. не?

вы уж как-то определитесь, что нужно.

перечисление по ключам в XSO тоже есть. и даже тип можно запросить. массив, строка, число и т.д.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
20 минут назад, krapotkin сказал:

если у вас на входе то массив, то объект, вам все равно придется работать с ними по разному. не?

У меня на входе всегда массив. Ключи ни когда не известны, так как это ID товара. Но иногда {}, а иногда [], т.е. без ключей.

Я банально хочу, что бы к любому полю на любом уровне можно было обратиться как по имени, так и по индексу, и что бы не через задницу это делать. Это единственное требование. Не думал, что хочу слишком много. :D
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

вы вообще читаете что вам пишут? в JSON массив это [] а объект - {}

что там у вас на входе парсер абсолютно не интересует. вы ему говорите, массив парсить или объект. и он все делает в соответствии со спецификацией.

и на любом уровне и в объекте и в массиве вы можете обратиться как по индексу, так и по ключу. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
47 минут назад, krapotkin сказал:

вы вообще читаете что вам пишут? в JSON массив это [] а объект - {}

Я это прекрасно знаю. Но зачем плодить 100500 разных классов для описания одного и того-же? Не. Кому нравится кривая архитектура пожалуйста. Есть System.JSON, который имеет как раз 100500 классов, и который эксепшенами плюётся постоянно. Но если для нормальных людей. Зачем эта кривость? Почему нельзя иметь один класс на уровень, который всё отдаст как надо? Когда нет какого-то поля то будет культурное сообщение, а не эксепшен. Когда к полю можно обратиться по имени, а можно по индексу и так далее. Это космически-недостижимые технологии?

Почему я не хочу 100500 классов? Потому что там везде придётся прописать один и тот-же код, а при доработках моих коллег править придётся код в более чем одном месте. А парсинг там и так не простой в плане дикого количества ньюансов. Так что это  равносильно прямо пропорциональному увеличению проблем, которые начнут вылазить, например, через месяц. Причём в среднем 1 раз в месяц.

Я бы с удовольствием остановился на tiny-json, если бы не вышеописанные проблемы с Child[].Но как я понял нормальных JSON парсеров, как не удивительно, на дельфе нет. Придётся писать велосипед. :( 
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Если пытаться кормить json парсер кривым json и ожидать, что почему вдруг объект станет неожиданно массивом и не будет исключений, то таких парсеров вам не найти. Проще написать самому: быстро, дешево, без 100500 классов и исключений. И такой, который будет считать, что {} - это массив.

А вообще, рекомендую начать с http://www.json.org/

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
23 часа назад, Akad сказал:

Почему я не хочу 100500 классов? Потому что там везде придётся прописать один и тот-же код, а при доработках моих коллег править придётся код в более чем одном месте. А парсинг там и так не простой в плане дикого количества ньюансов. Так что это  равносильно прямо пропорциональному увеличению проблем, которые начнут вылазить, например, через месяц. Причём в среднем 1 раз в месяц.

хотите облегчить себе жить? ваших коллег не следует допускать к бэкенду.

изучите все вместе структуру json и приведите ответы сервера в порядок. 

я давно для себя придумал структуру ответов и незнаю горя

для ошибки

{
  "status": "ERROR",
  "text": "Тут текст ошибки"
}

для данных структура всегда одна - data ВСЕГДА массив, ну а в элементах массива уже что хотите

{
  "status": "OK",
  "data": [
    {
      "id": 1,
      "name": "asdasd"
    }
  ]
}

есть такая штука (писалось для себя), ну и не боитесь использовать де/маршалинг 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Гость
Эта тема закрыта для публикации ответов.

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу