You are not logged in.
Pages: 1
I have the following two classes:
type TListaEstados = class
private
flista:TObjectList<TEstado>;
public
constructor Create;
published
property estados:TObjectList<TEstado> read flista write flista;
end;
type
TEstado = class
private
fcodigo: Integer;
fnome: string;
fsigla: string;
published
property codigo: Integer read fcodigo write fcodigo;
property nome: string read fnome write fnome;
property sigla: string read fsigla write fsigla;
end;
And I want to serialize a TListaEstados object. Ideally, I'd like to use the
MyString := SynCrossPlatformJson.ObjectToJSON(MyObject);
function, but as it is, it returns me json like this:
{"estados":"null"}
I already tried inheriting from TInterfacedCollection, but it gave me an Access Violation. I also tried to register the class like below:
TJSONSerializer.RegisterClassForJSON(TListaEstados);
And the output is the same as above. So, where should I begin? How can I serialize this?
Thanks.
Offline
TObjectList<TEstado> is just not supported directly.
From the RTTI, there is no easy way of getting the TEstado type from its TObjectList<TEstado> class information..
Try to use simply a TSynAutoCreateFields, and an T*ObjArray.
Offline
Thanks for the answer, but I couldn't find what this T*ObjArray is.
But if I was to change TObjectList<TEstado> to a dynamic array of TEstado, could I serialize it then? How?
Thanks again.
Last edited by Jorge_Ricardo (2015-10-15 18:45:25)
Offline
In order to use generics with the mORMot server you could do as followed:
uses
System.Generics.Collections;
System.SysUtils,
System.JSON,
REST.Json,
mORMot,
SynCommons;
type
TEstadoObjectList = class(TObjectList<TEstado>);
IEstadoService = interface(IInvokable)
['{A56EA833-873A-4AA5-9786-DA7DC1A7D014}']
function GetEstados(out AList: TEstadoObjectList): boolean;
end;
TEstadoService = class(TInterfacedObject, IEstadoService)
public
function GetEstados(out AList: TEstadoObjectList): boolean;
end;
TJSONSerializerEstado = class(TObject)
public
class function ReadJSON(const aValue: TObject; aFrom: PUTF8Char; var aValid: Boolean; aOptions: TJSONToObjectOptions): PUTF8Char;
class procedure WriteJSON(const aSerializer: TJSONSerializer; aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
end;
implementation
class function TJSONSerializerEstado.ReadJSON(const aValue: TObject; aFrom: PUTF8Char; var aValid: Boolean; aOptions: TJSONToObjectOptions): PUTF8Char;
begin
// not yet written...
end;
class procedure TJSONSerializerEstado.WriteJSON(const aSerializer: TJSONSerializer; aValue: TObject; aOptions: TTextWriterWriteObjectOptions);
var
I: Integer;
EL: TEstadoObjectList;
JSONObject: TJSOnObject;
begin
EL := TEstadoObjectList(aValue);
JSONObject := nil;
TRY
JSONObject := TJson.ObjectToJsonObject(EL);
aSerializer.AddString(JSONObject.Values['items'].ToJSON);
FINALLY
for I := (EL.Count-1) downto 0 do
begin
EL[i].Free;
EL[i] := nil;
EL.Delete(I);
end;
FreeAndNil(JSONObject);
END;
end;
function TEstadoService.GetEstados(out AList: TEstadoObjectList): boolean;
var
Estado: TEstado;
I: Integer;
begin
AList.Capacity := 10;
for I := 1 to AList.Capacity do
begin
Estado := TEstado.Create;
Estado.ID := 123456;
Estado.Name := 'abcdefg';
AList.Add(Estado);
end;
Result := true;
end;
initialization
TJSONSerializer.RegisterCustomSerializer(TEstadoObjectList, TJSONSerializerEstado.ReadJSON, TJSONSerializerEstado.WriteJSON);
TJSONSerializer.RegisterClassForJSON([TEstadoObjectList]);
TInterfaceFactory.RegisterInterfaces([TypeInfo(IEstadoService)]);
finalization
Then, you can call your service as http://localhost:8080/root/EstadoService/GetEstados and you will get something like:
{
"result": [
[
{
"iD": 123456,
"name": "abcdefg"
}
...
],
],
"id": 1
}
I hope, it helps! :-)
Last edited by cypriotcalm (2015-10-16 12:43:59)
Offline
Here is the reader method for the EstadoService
IEstadoService = interface(IInvokable)
['{A56EA833-873A-4AA5-9786-DA7DC1A7D014}']
function GetEstados(out AList: TEstadoObjectList): boolean;
procedure SaveEstados(const AList: TEstadoObjectList);
end;
...
procedure TEstadoDataService.SaveEstados(const AList: TEstadoObjectList);
var
I: Integer;
begin
TRY
if (AList.Count > 0) then
begin
Item1Name := AList[0].Name;
end;
FINALLY
for I := (AList.Count-1) downto 0 do
begin
AList[i].Free;
AList[i] := nil;
AList.Delete(I);
end;
END;
end;
...
// THE READER
class function TJSONSerializerEstado.ReadJSON(const aValue: TObject; aFrom: PUTF8Char; var aValid: Boolean; aOptions: TJSONToObjectOptions): PUTF8Char;
var
I: Integer;
ML: TEstadoObjectList;
Estado: TEstado;
JSONArray, JSONArrayRoot: TJSONArray;
JSONObject: TJSONObject;
lst: TEstadoObjectList;
JSONString: string;
begin
aValid := false;
Result := PUTF8Char('['+aFrom);
if (aValue is TEstadoObjectList) then
begin
JSONArray := nil;
JSONArrayRoot := nil;
TRY
JSONArrayRoot := TJSONObject.ParseJSONValue(Result) as TJSONArray;
if Assigned(JSONArrayRoot) and (JSONArrayRoot.Count > 0) then
begin
JSONArray := JSONArrayRoot.Items[0] as TJSONArray;
if Assigned(JSONArray) and (JSONArray.Count > 0) then
begin
ML := TEstadoObjectList(aValue);
ML.Capacity := JSONArray.Count;
for I := 0 to JSONArray.Count-1 do
begin
JSONString := JSONArray.Items[i].ToJSON;
if (JSONString <> '') then
begin
Estado := TJson.JsonToObject<TEstado>(JSONString);
if Assigned(Estado) then
begin
ML.Add(Estado);
end;
end;
end;
aValid := true;
end;
end;
FINALLY
FreeAndNil(JSONArrayRoot);
END;
end;
end;
Your POST request should look like this:
[[{
"iD": 1,
"name": "Estado 1"
},
{
"iD": 2,
"name": "Estado 2"
},
{
"iD": 3,
"name": "Estado 3"
}]]
Offline
Pages: 1