У вас какая то надуманная проблема. На самом деле "руками" все делается намного проще чем кажется. При этом код будет минимизировать ошибки, потому что он будет типовой, шаблонный. Вот я приведу кусочек код из одной моей программы:
unit Rest.API;
interface
uses
CodeSiteLogging,
System.JSON, REST.JsonReflect, Rest.Classes,
System.SysUtils, System.Classes, IPPeerClient, REST.Client, REST.Types, Data.Bind.Components, Data.Bind.ObjectScope;
type
TApiObject = class abstract
end;
TApiLogin = class(TApiObject)
public
Login: string;
Password: string;
end;
TRestAPI = class(TDataModule)
RESTClient: TRESTClient;
RESTRequest: TRESTRequest;
RESTResponse: TRESTResponse;
private
const BaseURL = 'http://bla-bla.com/index.php';
private
// Выполняет запрос
function Request(ABody: TApiObject): TJSONValue;
function SendLogin(ABody: TApiLogin): TJSONValue;
function SendRegistry(ABody: TApiUser): TJSONValue;
function GetUserInfo(ABody: TApiInfo): TJSONValue;
function SetBalance(ABody: TApiBalance): TJSONValue;
public
function SendRequest(AObject: TApiObject; AOwn: Boolean = true): TJSONValue;
end;
var
RestAPI: TRestAPI;
implementation
{%CLASSGROUP 'FMX.Controls.TControl'}
{$R *.dfm}
{ TDataHTTP }
/// Основная функция отправки json-объекта. она принимает обычный объект и сериализует его в json
function TRestAPI.Request(ABody: TApiObject): TJSONValue;
var
i: integer;
begin
RESTRequest.ClearBody;
RESTRequest.AddBody(ABody);
RESTRequest.Execute;
/// проверяем ответ сервера
if (RESTResponse.StatusCode <> 200) then
raise Exception.CreateFmt('Оштбка сервера %d "%s"',[RESTResponse.StatusCode, RESTResponse.StatusText]);
/// проверяем, содержит ли ответ json
if not Assigned(RESTResponse.JSONValue) then
raise Exception.Create('Ответ сервера не содержит подходящих данных');
/// Проверяем, не содержится ли в ответе ошибок
Result := RESTResponse.JSONValue.GetValue<TJSONValue>('content');
if not RESTResponse.JSONValue.GetValue<string>('status').Equals('success') then
raise Exception.Create(RESTResponse.JSONValue.GetValue<string>('error'));
end;
/// Так делаем отправку на конкретный URL
/// Запрос логина (проверка существования пользователя)
function TRestAPI.SendLogin(ABody: TApiLogin): TJSONValue;
begin
RESTClient.BaseURL := BaseURL + '?act=users&area=login&response=js';
Result := Request(ABody);
end;
/// регистрация нового пользователя
function TRestAPI.SendRegistry(ABody: TApiUser): TJSONValue;
begin
RESTClient.BaseURL := BaseURL + '?act=terminal&area=create®isterType=2&response=js';
Result := Request(ABody);
end;
/// Информация о пользователе
function TRestAPI.GetUserInfo(ABody: TApiInfo): TJSONValue;
begin
RESTClient.BaseURL := BaseURL + '?act=terminal&area=info&infoType=2&response=js';
Result := Request(ABody);
end;
/// Изменить баланс пользователя
function TRestAPI.SetBalance(ABody: TApiBalance): TJSONValue;
begin
RESTClient.BaseURL := BaseURL + '?act=terminal&area=cash&response=js';
Result := Request(ABody);
end;
/// Это не обязательная функция, она просто упрощает работу. По сути просто вызывает нужную функцию,
/// в зависимости от переданного объекта. после отправки запроса, удаляет объект из памяти.
function TRestAPI.SendRequest(AObject: TApiObject; AOwn: Boolean): TJSONValue;
begin
try
if (AObject is TApiLogin) then
Result := SendLogin(AObject as TApiLogin)
else
if (AObject is TApiUser) then
Result := SendRegistry(AObject as TApiUser)
else
if (AObject is TApiInfo) then
Result := GetUserInfo(AObject as TApiInfo)
else
if (AObject is TApiBalance) then
Result := SetBalance(AObject as TApiBalance)
finally
if AOwn and Assigned(AObject) then
FreeAndNil(AObject);
end;
end;
end.
А работать с этим так:
procedure DoLogin(const AUser, APassw: string);
var
Usr: TApiLogin;
Jsn: TJsonObject;
begin
Usr := TApiLogin.Create;
Usr.Login := AUser;
Usr.Password := APassw;
Jsn := RestAPI.SendRequest(Usr, True);
end;
Следует заметить, что все запросы возвращают json. Просто потому что мне так было нужно. Однако можно немного изменить функцию Request, что бы возвращался объект конкретного типа.