Reputation: 1429
I'm trying to implement a function which returns a json object containing elements of class. Here is my function:
procedure ListToJson(AInputList: TList<TRating>;
AResponse: TJSONObject);
var
i: Integer;
jsonPair: TJSONPair;
jsonObject: TJSONObject;
jsonArray: TJSONArray;
begin
jsonArray := TJSONArray.Create();
jsonObject := TJSONObject.Create();
jsonPair := TJSONPair.Create('ratings', jsonArray);
for i := 0 to AInputList.Count - 1 do
begin
jsonObject.AddPair(TJSONPair.Create('idrating', IntToStr(AInputList[i].IdRating)));
jsonObject.AddPair(TJSONPair.Create('idmark', IntToStr(AInputList[i].IdMark)));
jsonObject.AddPair(TJSONPair.Create('value', IntToStr(AInputList[i].Value)));
jsonObject.AddPair(TJSONPair.Create('description', AInputList[i].Description));
jsonObject.AddPair(TJSONPair.Create('timeposted', FormatDateTime('yyyy-mm-dd hh:mm:ss', AInputList[i].TimePosted)));
jsonArray.AddElement(jsonObject);
end;
AResponse.AddPair(jsonPair);
end;
And when I test it with a list which contains two elements the returned string is:
{
"ratings":[{
"idrating":"1",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:03",
"idrating":"2",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:24"
},{
"idrating":"1",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:03",
"idrating":"2",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:24"
}]
}
I tried to remove all pairs after each loop iteration:
procedure ListToJson(AInputList: TList<TRating>;
AResponse: TJSONObject);
var
i: Integer;
jsonPair: TJSONPair;
jsonObject: TJSONObject;
jsonArray: TJSONArray;
begin
jsonArray := TJSONArray.Create();
jsonObject := TJSONObject.Create();
jsonPair := TJSONPair.Create('ratings', jsonArray);
for i := 0 to AInputList.Count - 1 do
begin
jsonObject.AddPair(TJSONPair.Create('idrating', IntToStr(AInputList[i].IdRating)));
jsonObject.AddPair(TJSONPair.Create('idmark', IntToStr(AInputList[i].IdMark)));
jsonObject.AddPair(TJSONPair.Create('value', IntToStr(AInputList[i].Value)));
jsonObject.AddPair(TJSONPair.Create('description', AInputList[i].Description));
jsonObject.AddPair(TJSONPair.Create('timeposted', FormatDateTime('yyyy-mm-dd hh:mm:ss', AInputList[i].TimePosted)));
jsonArray.AddElement(jsonObject);
jsonObject.RemovePair('idrating');
jsonObject.RemovePair('idmark');
jsonObject.RemovePair('value');
jsonObject.RemovePair('description');
jsonObject.RemovePair('timeposted');
end;
AResponse.AddPair(jsonPair);
end;
And the ouput is an array with n(count of list elements) empty objects: {"ratings":[{},{}]}
And the json I'm trying to build should be like:
{
"ratings":[{
"idrating":"1",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:03"
},{
"idrating":"2",
"idmark":"0",
"value":"0",
"description":"",
"timeposted":"2015-07-29 11:25:24"
}]
}
Upvotes: 4
Views: 25140
Reputation: 36840
Is it me, or is that just really ugly (and codous, or what's the word for a lot of code for what it does). Since I really (really) hate to see long lists of overloads for all kinds of types, and really (really) like the Variant
type, I've created jsonDoc, and it would look like this:
var
x:array of OleVariant;
i:integer;
begin
SetLength(x,AInputList.Count);
for i:=0 to AInputListCount-1 do
x[i]:=JSON(
['idrating',AInputList[i].IdRating
,'idmark',AInputList[i].IdMark
,'value',AInputList[i].Value
,'description',AInputList[i].Description
,'timeposted',FormatDateTime('yyyy-mm-dd hh:mm:ss', AInputList[i].TimePosted)//VarFromDateTime?
]);
end;
AResponse:=JSON(['ratings',VarArrayOf(x)]);
Upvotes: 2
Reputation: 62531
You have one jsonObject, so whatever state it ends up in is repeated each time you add it to the array.
Construct jsonObject within the loop, and then you will have different objects in your array.
for i := 0 to AInputList.Count - 1 do
begin
jsonObject := TJSONObject.Create();
jsonObject.AddPair(TJSONPair.Create('idrating', IntToStr(AInputList[i].IdRating)));
jsonObject.AddPair(TJSONPair.Create('idmark', IntToStr(AInputList[i].IdMark)));
jsonObject.AddPair(TJSONPair.Create('value', IntToStr(AInputList[i].Value)));
jsonObject.AddPair(TJSONPair.Create('description', AInputList[i].Description));
jsonObject.AddPair(TJSONPair.Create('timeposted', FormatDateTime('yyyy-mm-dd hh:mm:ss', AInputList[i].TimePosted)));
jsonArray.AddElement(jsonObject);
end;
Alternatly, you can define a function to create a TJSONObject from a TRating, and use that in your loop
function TRatingToJSON( Rating: TRating ): TJSONObject;
begin
Result := TJSONObject.Create();
Result.AddPair(TJSONPair.Create('idrating', IntToStr(Rating.IdRating)));
Result.AddPair(TJSONPair.Create('idmark', IntToStr(Rating.IdMark)));
Result.AddPair(TJSONPair.Create('value', IntToStr(Rating.Value)));
Result.AddPair(TJSONPair.Create('description', Rating.Description));
Result.AddPair(TJSONPair.Create('timeposted', FormatDateTime('yyyy-mm-dd hh:mm:ss', Rating.TimePosted)));
end;
procedure ListToJson(AInputList: TList<TRating>;
AResponse: TJSONObject);
var
i: Integer;
jsonArray: TJSONArray;
begin
jsonArray := TJSONArray.Create();
for i := 0 to AInputList.Count - 1 do
begin
jsonArray.AddElement(TRatingToJSON(AInputList[i]));
end;
AResponse.AddPair(TJSONPair.Create('ratings', jsonArray));
end;
Upvotes: 10
Reputation: 1429
Found a workraround:
procedure ListToJson(AInputList: TList<TRating>;
AResponse: TJSONObject);
var
i: Integer;
jsonPair: TJSONPair;
jsonObject: TList<TJSONObject>;
jsonArray: TJSONArray;
begin
jsonArray := TJSONArray.Create();
jsonObject := TList<TJSONObject>.Create;
jsonPair := TJSONPair.Create('ratings', jsonArray);
try
for i := 0 to AInputList.Count - 1 do
begin
jsonObject.Add(TJSONObject.Create());
jsonObject.Last.AddPair(TJSONPair.Create('idrating', IntToStr(AInputList[i].IdRating)));
jsonObject.Last.AddPair(TJSONPair.Create('idmark', IntToStr(AInputList[i].IdMark)));
jsonObject.Last.AddPair(TJSONPair.Create('value', IntToStr(AInputList[i].Value)));
jsonObject.Last.AddPair(TJSONPair.Create('description', AInputList[i].Description));
jsonObject.Last.AddPair(TJSONPair.Create('timeposted', FormatDateTime('yyyy-mm-dd hh:mm:ss', AInputList[i].TimePosted)));
jsonArray.AddElement(jsonObject.Last);
end;
AResponse.AddPair(jsonPair);
finally
jsonObject.Free;
end;
end;
Upvotes: 0