Сериализация JSON-массива в IList с использованием Spring4D в Delphi
Введение
При работе с современными приложениями на Delphi часто возникает необходимость сериализации данных между форматами, особенно между JSON и объектами или записями. В этой статье мы рассмотрим, как правильно сериализовать JSON-массив в интерфейс IList<T> из фреймворка Spring4D, где T - это запись (record).
Проблема
Основная сложность, с которой сталкиваются разработчики, заключается в том, что стандартные механизмы сериализации в Delphi (как встроенные, так и сторонние библиотеки) хорошо работают с TList<T> из System.Generics.Collections, но не всегда поддерживают IList<T> из Spring4D.
Решение 1: Создание собственного конвертера JSON
Первый подход предполагает создание специализированного конвертера для Spring4D коллекций. Вот пример реализации:
unit Spring4DJsonConverter;
interface
uses
System.SysUtils,
System.JSON.Serializers,
System.JSON.Converters,
System.JSON.Writers,
System.JSON.Readers,
Spring.Collections,
Spring;
type
TSpringListJsonConverter<T> = class(TJsonConverter)
protected
function CreateList: IList<T>; virtual;
public
procedure WriteJson(const AWriter: TJsonWriter; const AValue: TValue;
const ASerializer: TJsonSerializer); override;
function ReadJson(const AReader: TJsonReader; ATypeInf: PTypeInfo;
const AExistingValue: TValue; const ASerializer: TJsonSerializer): TValue; override;
function CanConvert(ATypeInf: PTypeInfo): Boolean; override;
end;
implementation
uses
System.Rtti,
System.TypInfo;
function TSpringListJsonConverter<T>.CanConvert(ATypeInf: PTypeInfo): Boolean;
begin
Result := (ATypeInf.Kind = tkInterface) and
(GetTypeData(ATypeInf).GUID = IList<T>.DefaultGuid);
end;
function TSpringListJsonConverter<T>.CreateList: IList<T>;
begin
Result := TCollections.CreateList<T>;
end;
function TSpringListJsonConverter<T>.ReadJson(const AReader: TJsonReader;
ATypeInf: PTypeInfo; const AExistingValue: TValue;
const ASerializer: TJsonSerializer): TValue;
var
List: IList<T>;
Items: TArray<T>;
begin
if AReader.TokenType = TJsonToken.Null then
Exit(TValue.Empty);
Items := ASerializer.Deserialize<TArray<T>>(AReader);
if not AExistingValue.IsEmpty then
List := AExistingValue.AsType<IList<T>>
else
List := CreateList;
List.AddRange(Items);
Result := TValue.From<IList<T>>(List);
end;
procedure TSpringListJsonConverter<T>.WriteJson(const AWriter: TJsonWriter;
const AValue: TValue; const ASerializer: TJsonSerializer);
var
List: IList<T>;
begin
if AValue.TryAsType<IList<T>>(List) then
ASerializer.Serialize(AWriter, List.ToArray)
else
raise EJsonException.Create('Невозможно сериализовать IList<T>');
end;
end.
Использование конвертера
uses
System.JSON.Serializers,
Spring.Collections,
Spring4DJsonConverter;
type
TPerson = record
Name: string;
Age: Integer;
end;
procedure TestSpring4DJson;
var
Serializer: TJsonSerializer;
People: IList<TPerson>;
Json: string;
begin
Serializer := TJsonSerializer.Create;
try
// Регистрируем наш конвертер
Serializer.Converters.Add(TSpringListJsonConverter<TPerson>.Create);
// Десериализация JSON в IList<T>
Json := '[{"Name":"Иван","Age":30},{"Name":"Мария","Age":25}]';
People := Serializer.Deserialize<IList<TPerson>>(Json);
// Сериализация обратно в JSON
Json := Serializer.Serialize(People);
WriteLn(Json);
finally
Serializer.Free;
end;
end;
Решение 2: Адаптация библиотеки DelphiJSON
Если вы предпочитаете использовать библиотеку DelphiJSON, можно модифицировать ее для поддержки Spring4D коллекций. Вот как это можно сделать:
// Модифицированная версия DelphiJSON для поддержки Spring4D
function DelphiJSON<T>.DeserializeToSpringList(const Json: string;
const Settings: TDJSettings = nil): IList<T>;
var
TempArray: TArray<T>;
begin
TempArray := Deserialize<TArray<T>>(Json, Settings);
Result := TCollections.CreateList<T>;
Result.AddRange(TempArray);
end;
Использование:
var
People: IList<TPerson>;
begin
People := DelphiJSON<TPerson>.DeserializeToSpringList(JsonString);
// Работаем с коллекцией...
end;
Альтернативное решение: Использование TList с последующим преобразованием
Если по каким-то причинам предыдущие решения не подходят, можно использовать промежуточное преобразование:
function JsonToSpringList<T>(const Json: string): IList<T>;
var
TempList: TList<T>;
begin
TempList := TList<T>.Create;
try
// Используем стандартную десериализацию
TempList := DelphiJSON<T>.Deserialize(Json);
Result := TCollections.CreateList<T>;
Result.AddRange(TempList.ToArray);
finally
TempList.Free;
end;
end;
Заключение
В этой статье мы рассмотрели несколько способов решения проблемы сериализации JSON-массивов в IList<T> из Spring4D. Выбор конкретного подхода зависит от ваших требований и предпочтений. Создание собственного конвертера дает наибольшую гибкость, в то время как адаптация существующей библиотеки может быть быстрее в реализации.
Не забывайте, что Spring4D предоставляет мощные возможности для работы с коллекциями, и их интеграция с современными форматами данных, такими как JSON, значительно упрощает разработку сложных приложений на Delphi.
Статья описывает методы сериализации JSON-массивов в интерфейс `IList` из фреймворка Spring4D в Delphi, включая создание собственного конвертера и адаптацию сторонних библиотек.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.