Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Решение проблемы EInsufficientRtti при преобразовании объектов TSignalBox в JSON в Delphi.

Delphi , Интернет и Сети , Json

 

Введение

При работе с JSON в Delphi разработчики часто сталкиваются с ошибкой EInsufficientRtti, которая возникает при попытке сериализации или десериализации объектов, не имеющих достаточной информации RTTI (Run-Time Type Information). В этой статье мы рассмотрим причины этой ошибки при работе с объектами типа TSignalBox и предложим несколько способов её решения.

Понимание проблемы EInsufficientRtti

Ошибка EInsufficientRtti возникает, когда система RTTI в Delphi не может получить достаточно информации о типе для выполнения операции сериализации или десериализации. Это часто происходит с классами, которые:

  1. Не наследуются от TPersistent или TComponent
  2. Не имеют опубликованных (published) свойств
  3. Используют сложные типы данных без регистрации их конвертеров

Пример кода, который может вызвать эту ошибку:

type
  TSignalBox = class
  private
    FSignalName: string;
    FSignalValue: Integer;
  public
    property SignalName: string read FSignalName write FSignalName;
    property SignalValue: Integer read FSignalValue write FSignalValue;
  end;

var
  SignalBox: TSignalBox;
  JsonString: string;
begin
  SignalBox := TSignalBox.Create;
  try
    SignalBox.SignalName := 'TestSignal';
    SignalBox.SignalValue := 42;

    // Эта строка вызовет EInsufficientRtti
    JsonString := TJson.ObjectToJsonString(SignalBox);
  finally
    SignalBox.Free;
  end;
end;

Основные решения проблемы

1. Наследование от TPersistent и использование published свойств

Самый простой способ решить проблему - сделать свойства опубликованными (published) и унаследовать класс от TPersistent:

type
  TSignalBox = class(TPersistent)
  private
    FSignalName: string;
    FSignalValue: Integer;
  published
    property SignalName: string read FSignalName write FSignalName;
    property SignalValue: Integer read FSignalValue write FSignalValue;
  end;

Этот подход работает, так как компилятор генерирует RTTI для всех опубликованных свойств классов, унаследованных от TPersistent.

2. Использование атрибутов для сериализации

В более новых версиях Delphi можно использовать атрибуты для управления сериализацией:

uses
  System.JSON.Serializers;

type
  TSignalBox = class
  private
    [JsonName('SignalName')]
    FSignalName: string;
    [JsonName('SignalValue')]
    FSignalValue: Integer;
  public
    property SignalName: string read FSignalName write FSignalName;
    property SignalValue: Integer read FSignalValue write FSignalValue;
  end;

3. Регистрация пользовательских конвертеров

Для сложных случаев можно зарегистрировать пользовательский конвертер:

type
  TSignalBoxConverter = class(TJsonConverter<TSignalBox>)
  public
    function ToJson(const Value: TSignalBox): string; override;
    function FromJson(const Value: string): TSignalBox; override;
  end;

function TSignalBoxConverter.ToJson(const Value: TSignalBox): string;
var
  JsonObj: TJSONObject;
begin
  JsonObj := TJSONObject.Create;
  try
    JsonObj.AddPair('SignalName', Value.SignalName);
    JsonObj.AddPair('SignalValue', TJSONNumber.Create(Value.SignalValue));
    Result := JsonObj.ToString;
  finally
    JsonObj.Free;
  end;
end;

function TSignalBoxConverter.FromJson(const Value: string): TSignalBox;
var
  JsonObj: TJSONObject;
begin
  Result := TSignalBox.Create;
  JsonObj := TJSONObject.ParseJSONValue(Value) as TJSONObject;
  try
    if Assigned(JsonObj) then
    begin
      Result.SignalName := JsonObj.GetValue<string>('SignalName');
      Result.SignalValue := JsonObj.GetValue<Integer>('SignalValue');
    end;
  finally
    JsonObj.Free;
  end;
end;

// Регистрация конвертера
TJsonSerializer.RegisterConverter(TSignalBox, TSignalBoxConverter);

Альтернативные решения

1. Использование ручной сериализации

Если предыдущие методы не подходят, можно реализовать ручную сериализацию:

function TSignalBox.ToJson: string;
var
  JsonObj: TJSONObject;
begin
  JsonObj := TJSONObject.Create;
  try
    JsonObj.AddPair('SignalName', FSignalName);
    JsonObj.AddPair('SignalValue', TJSONNumber.Create(FSignalValue));
    Result := JsonObj.ToString;
  finally
    JsonObj.Free;
  end;
end;

class function TSignalBox.FromJson(const JsonString: string): TSignalBox;
var
  JsonObj: TJSONObject;
begin
  Result := TSignalBox.Create;
  JsonObj := TJSONObject.ParseJSONValue(JsonString) as TJSONObject;
  try
    if Assigned(JsonObj) then
    begin
      Result.SignalName := JsonObj.GetValue<string>('SignalName');
      Result.SignalValue := JsonObj.GetValue<Integer>('SignalValue');
    end;
  finally
    JsonObj.Free;
  end;
end;

2. Использование сторонних библиотек

Существуют сторонние библиотеки для работы с JSON, которые могут обойти ограничения стандартного механизма:

  1. SuperObject
  2. GrijjyFoundation
  3. dwsJSON

Пример с SuperObject:

uses
  SuperObject;

function TSignalBox.ToJson: ISuperObject;
begin
  Result := SO;
  Result.S['SignalName'] := FSignalName;
  Result.I['SignalValue'] := FSignalValue;
end;

class function TSignalBox.FromJson(const Json: ISuperObject): TSignalBox;
begin
  Result := TSignalBox.Create;
  Result.SignalName := Json.S['SignalName'];
  Result.SignalValue := Json.I['SignalValue'];
end;

Лучшие практики

  1. Проектирование классов: Заранее планируйте, какие классы будут сериализоваться в JSON, и проектируйте их соответствующим образом.

  2. Документирование: Документируйте, какие свойства должны быть сериализованы и в каком формате.

  3. Тестирование: Всегда тестируйте сериализацию и десериализацию с различными наборами данных.

  4. Обработка ошибок: Обеспечьте корректную обработку ошибок при парсинге JSON.

Заключение

Ошибка EInsufficientRtti при работе с JSON в Delphi может быть решена несколькими способами, в зависимости от требований проекта. Самый простой подход - наследование от TPersistent и использование published свойств. Для более сложных сценариев можно использовать атрибуты, пользовательские конвертеры или ручную сериализацию. Выбор метода зависит от конкретных требований к производительности, гибкости и поддерживаемым версиям Delphi.

Создано по материалам из источника по ссылке.

Статья описывает решение проблемы EInsufficientRtti при преобразовании объектов TSignalBox в JSON в Delphi, предлагая различные методы, включая наследование от TPersistent, использование атрибутов и ручную сериализацию.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Json ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-12 13:04:48/0.0055520534515381/0