В последний раз я более менее подробно рассказывал о работе с JSON в Delphi года три назад, когда актуальной была Delphi XE2. Однако все течет, всё меняется и сейчас у нас уже есть Delphi XE7 с новыми возможностями, крутыми штуками типа AppTethering и FireUI, а вместе с этим и с менее заметными, но, тем не менее, серьезными изменениями в работе с JSON в Delphi.
Надо сказать, что с того момента, как в Delphi появилась своя собственная библиотека для работы с JSON, мы перевели абсолютно все свои компоненты для работы с онлайн-сервисами именно на работу с данными в формате JSON и, надо сказать, что ничуть не жалеем. Иногда по Сети приходится «ворочать» довольно большие объемы данных и компактный JSON тут оказывается как нельзя кстати. Однако, вместе с этим, не сильно торопились переезжать на новые версии Delphi — на момент написания этой статьи пока ещё используется Delphi XE3. Но в ближайшую неделю-две будет переезд на Delphi XE7 (надеюсь удачный). И так как переезд будет по-любому, я решил проверить работу всех своих компонентов в XE7.
Первое, что сразу становится понятным — это то, что теперь все классы для работы JSON «переехали» в модуль System.JSON. Переезд это произошел намного ранее, чем вышла XE7, но, когда точно сейчас сказать не могу…скорее всего в XE5. В общем переехали классы и бог с ними — пусть будет System.JSON. Так даже логичнее.
Просто, чтобы ни у кого не возникало лишних вопросов, договоримся сразу:
Теперь посмотрим на изменения в классах.
У всех классов-наследников TJSONAncestor появился новый метод:
function ToJSON: string;
Метод, как можно догадаться из его описания, представляет какой-либо JSON-элемент в виде обычной строки. В принципе, причина появления этого метода мне не совсем ясна, т.к. у нас уже имеется метод ToString, который делает ровно то же самое.
Серьезные изменения произошли в классе TJSONObject. Так один из методов Get и метод Size теперь помечены как deprecated:
function Get(const Index: Integer): TJSONPair; overload; deprecated 'Use Pairs property'; function Size: Integer; inline; deprecated 'Use Count Property';
Вместе с этим, для работы с парами и их значениями у нас теперь появились такие свойства:
property Count: Integer read GetCount; property Pairs[const Index: Integer]: TJSONPair read GetPair; property Values[const Name: string]: TJSONValue read GetValue;
Также появился новые метод:
function GetValue(const Name: string): TJSONValue; overload;
с помощью которого можно получить значение пары с именем Name.
Аналогичные изменения произошли и в классе TJSONArray. Так, помечены как deprecated:
function Size: Integer; inline; deprecated 'Use Count Property'; function Get(const Index: Integer): TJSONValue; deprecated 'Use Items property';
Вместо этого появились свойства:
property Count: Integer read GetCount; property Items[const Index: Integer]: TJSONValue read GetValue;
Появились новые методы для работы с числами с плавающей точкой в JSON:
function FloatToJson(const Value: Double): string; function JsonToFloat(const DotValue: string): Double; function TryJsonToFloat(const DotValue: string; var Value: Double): Boolean;
Что дали в итоге эти и другие изменения в библиотеке для работы с JSON в Delphi? Как минимум более лаконичный и читабельный код.
Что же касается скорости работы, то здесь я был приятно удивлен тем, что в Delphi XE7 JSON стал парсится быстрее. В качестве примера я взял файл размером 61 Mb, содержащий массив на 10000 элементов. Каждый элемент — JSON-объект с различными данными. Чтобы проверить скорость парсинга я написал в XE3 и XE7 две абсолюно одинаковые прогаммки, следующего содержания:
var iCounterPerSec: TLargeInteger; T1, T2: TLargeInteger; Str: TStringStream; JSON: TJSONValue; begin if OpenDialog1.Execute then begin Str:=TStringStream.Create; try Str.LoadFromFile(OpenDialog1.FileName); QueryPerformanceFrequency(iCounterPerSec); QueryPerformanceCounter(T1); JSON:=TJSONObject.ParseJSONValue(Str.DataString); QueryPerformanceCounter(T2); Label1.Caption:=FormatFloat('0.0000', (T2 - T1) / iCounterPerSec) + ' сек.'; finally Str.Free; end; end; end;
- Результат в Delphi XE7 — 11,6139 сек.
- Результат в Delphi XE3 — 15,8304 сек.
Разница более чем в 4 сек., по-моему, достаточно значительна. Что же касается моей проверки, то код XE3 скомпилировался без ошибок в Xe7. Конечно, пришлось убрать использование всех методов, которые помечены deprecated, чтобы не словить, например, в Delphi XE8 или XE10 (если когда-то будем переходить) неприятненькие сюрпризы в виде убранных методов. В целом же — с работой с JSON в Delphi XE7 всё супер.
Не давно тоже заморачивался JSON, но стандартныя либа меня неустроила ни по скорости, ни по удобству работы, пришлось воять свою. Теперь все устраивает выложил может кому-то будет интересно https://sourceforge.net/projects/fastjsonlib/.
Произвел некоторые оптимизации… Тестировал на файле 110Мб ~2,7 млн элементов получилось 3,8 сек.
Отличная библиотека. как по скорости, так и удобству. Стандартная и рядом не стоит. Есть правда небольшие косяки в ней, к примеру: procedure TJSONObject.Clear(var AStr: string); var tmpCur,tmpLength : integer; <--- не используются объявленные переменные в процедуре ----- vtPChar: tmpValue := '"' + AArray[I].VPChar + '"'; <---- кастинг string и ansichar по утечкам памяти все классно, чисто и опрятно, что не сказать про стандартную либу делфи. Хотел бы узнать, как с вами связаться ? Внедрил вашу библиотеку к себе в проект, просто шикарно . как по памяти, так и по производительности, хотел бы с вами периодически связываться, предлагать идеи, узнавать об… Подробнее »
Привет. Сюда давно не заглядывал. Если нужно связаться jhonny_[собака]mail.ru
Влад можно пример парсинга JSON для наглядности!
Парсить массивы JSON получается нормально, а вот с этим разобраться не могу никак:
{«response»:{«upload_url»:»http:\/\/cs624121.vk.com\/upload.php?act=do_add&mid=308290015&aid=216925737&gid=0&hash=731e303939460cce672b572c9e3af472&rhash=2b8fa3ccc12301078edecdf00e330f39&swfupload=1&api=1″,»aid»:216925737,»mid»:308290015}}
Использую Dephi XE7
Везде примеры только с массивами JSON
Fastjsonlib работает отлично и быстро. Однако, при разработке для андрюши, на хе8 не работает. На винде все нормально. На андрюше парсит не правильно.