Using TMS WEB Core and JSON - json

Starting from a VCL project to TMS WEB Core, I can no longer use "System.JSON".
Having declared :
LJsonValue: TJsonValue;
LJsonArray: TJsonArray;
LJSonString: TJsonString;
How to translate VCL line
LJsonValue := LJsonValue.GetValue<TJSonValue>('choices');
LJSonString := LJSonArray.Items[0].GetValue<TJSONString>('text');
for TMS WEB Core? I can't find the solution not being comfortable with JSON.

Related

Delphi 2007 JSON array of string to TStringList

Embarcadero introduced JSON types with Delphi 2009, but I'm using Delphi 2007 without these JSON types.
I'm wanting to process a JSON string being an "array of strings" into a TStringList object.
e.g.
["Ford", "BMW", "Fiat"]
I guess it's string token type of processing ..
There is a third party Delphi unit that might be useful for this:
https://sourceforge.net/projects/lkjson/
uses uLkJSON;
var
AString:String;
AStringList:TStringList;
jsonbase,Items : TlkJSONbase; //as per 3rd party unit uLkJSON
I: Integer;
begin
AStringList:=TStringList.create;
AString := '["Ford", "BMW", "Fiat"]';
jsonbase := TlkJSON.ParseText(AString);
if Assigned(jsonbase) then
begin
for I := 0 to Pred(jsonbase.Count) do
begin
Items := jsonbase.Child[I];
AStringList.add(Items.Value);
end;
end;
Result := AStringList;
end;

How to create a function to convert a generic "TFPGObjectList" into a "TJsonArray"?

I'm new to fpc Lazarus and came from Delphi BackGround.
I need to create a method in order to convert Generic Object Lists into TJsonArray.
Delphi has it natively, but aparently FPC Lazarus doesn't.
Here is what I have:
generic class function TDAOJsonUtils.ObjectListToJsonArray<T>(aObjectList: T): TJsonArray;
var
I: Integer;
_JsonStr: TJSONStreamer;
_JsonObj: TJsonObject;
begin
result := TJsonArray.Create;
_JsonStr := TJSONStreamer.Create(nil);
try
for i := 0 to Pred(TFPGObjectList(aObjectList).Count) do
begin
_JsonObj := TJsonObject.Create;
end;
finally
FreeAndNil(_JsonStr);
end;
end;
It doesn't compile with and throw the following message at the "for loop" statement:
"generics without specialization cannot be used as a type for a variable"
Any tips?
Thank's in advance.

Delphi HMRC test-api.service.hmrc.gov.uk/hello/world

I'm trying the HMRC Developers HUB tutorials from:
https://developer.service.hmrc.gov.uk/api-documentation/docs/tutorials
I have tried two ways of the "Hello World", but keep getting:
{"code":"ACCEPT_HEADER_INVALID","message":"The accept header is missing or invalid"}
Example 1 REST Client:
procedure TForm1.btnTest_REST_ClientClick(Sender: TObject);
var
jValue: TJSONValue;
begin
RESTClient1.BaseURL := cbHMRC_Test_URLs.Text;
RESTRequest1.Execute;
jValue := RESTResponse1.JSONValue;
MemoContent.Text:= jValue.ToString;
end;
Example 2 TdHTTP:
procedure TForm1.btnTest_HTTPClick(Sender: TObject);
var
get_url: string;
resp: TMemoryStream;
begin
get_url := 'https://test-api.service.hmrc.gov.uk/hello/world';
resp := TMemoryStream.Create;
try
IdHttp1.Request.CustomHeaders.AddValue('Accept', 'application/vnd.hmrc.1.0+json');
IdHTTP1.Get(get_url, resp);
resp.Position := 0; // <-- add this!!
MemoContent.Lines.LoadFromStream(resp);
finally
resp.Free;
end;
end;
Both make the connection, but fail on the Header.
Any ideas about what I'm doing wrong?
I would suggest going with the REST components. I've used them significantly and they work quite well.
On the REST component side, your just missing the Request Accept value:
RESTRequest1.Accept := 'application/vnd.hmrc.1.0+json';
I tested your example to their hello world resource and received:
{"message":"Hello World"}
Looks like it's working.
For those of you struggling like me with how to implement the initial HMRC tutorials in Delphi, try the following.
Create a new application. I chose a Multi-Device / Blank Application option.
On the main form, add the following components:-
TRESTClient
TRESTRequest
TRESTResponse
TMemo
TButton
Add the System.JSON unit to the uses clause.
Set the Button1Click procedure as follows:-
procedure TForm1.Button1Click(Sender: TObject);
var
jValue: TJSONValue;
begin
RESTClient1.BaseURL := 'https://test-api.service.hmrc.gov.uk/hello/world';
RESTRequest1.Accept := 'application/vnd.hmrc.1.0+json';
RESTRequest1.Execute;
jValue := RESTResponse1.JSONValue;
Memo1.Text:= jValue.ToString;
end;
Run the program, click the button and voila!
I hope this helps someone

JSON nested object shows empty in rest debugger and RestResponse (XE6)

I use C++Builder XE6 Pro and have the following JSON response (see the full response here):
[
{
"id":"10186",
"dataset":"krs_podmioty",
"url":"https://api-v3.mojepanstwo.pl/dane/krs_podmioty/10186",
"mp_url":"https://mojepanstwo.pl/dane/krs_podmioty/10186",
"schema_url":"https://api-v3.mojepanstwo.pl/schemas/dane/krs_podmioty.json",
"global_id":"3157847",
"slug":"bank-millennium",
"score":12.13878,
"data":
{
"krs_podmioty.nazwa_organu_reprezentacji":"ZARZĄD",
"krs_podmioty.dotacje_ue_beneficjent_id":"0",
"krs_podmioty.liczba_prokurentow":0,
...
"gpw":true
}
...
]
I am using REST components, but when I try to parse this, both in the REST Debugger and at design/run-time, I am getting empty values for the "dataset":"krs_podmioty" elements, but the "gpw":true elements show correctly.
I've choosen the JSON root element as DataObject, and marked Nested
and set NestedElementDepth to 3. I have tried another settings as well, but without success.
How to get the "dataset":"krs_podmioty" values correctly ?
This is how I'm able to read those values:
uses
System.Json;
procedure TForm1.Button1Click(Sender: TObject);
var
jsonText: string;
jsonArray: TJsonArray;
dataObj: TJsonObject;
Jobj: TJsonObject;
krsPodmiotyNazwaOrganuReprezentacjiValue: TJsonValue;
krsPodmiotyDotacjeUeBeneficjentIdValue: TJsonValue;
krsPodmiotyLiczbaProkurentowValue: TJsonValue;
begin
jsonText := '[{Your JSON content here}]';
Jobj := TJSONObject.ParseJSONValue(jsonText) as TJsonObject;
jsonArray :=Jobj.GetValue('Dataobject') as TJsonArray;
dataObj := (jsonArray.Items[0] as TJsonObject).GetValue('data') as TJsonObject;
krsPodmiotyNazwaOrganuReprezentacjiValue := dataObj.GetValue('krs_podmioty.nazwa_organu_reprezentacji');
krsPodmiotyDotacjeUeBeneficjentIdValue := dataObj.GetValue('krs_podmioty.dotacje_ue_beneficjent_id');
krsPodmiotyLiczbaProkurentowValue := dataObj.GetValue('krs_podmioty.liczba_prokurentow');
MessageDlg(krsPodmiotyNazwaOrganuReprezentacjiValue.Value, mtInformation, [mbOK], 0, mbOK);
MessageDlg(krsPodmiotyDotacjeUeBeneficjentIdValue.Value, mtInformation, [mbOK], 0, mbOK);
MessageDlg(krsPodmiotyLiczbaProkurentowValue.Value, mtInformation, [mbOK], 0, mbOK);
end;
However, if you are not using anything from the System.Json namespace, this might not answer your question.

Issue with difference between Delphi XE4 and XE7 JSON marshalling of TPointF type

I am in the process of upgrading a project that was originally coded with Delphi XE4 using the new XE7 version. This application saves its main output as a marshaled JSON file that the users load, edit, save similar to what would be done with a Word document.
They do not work directly with the json, it is just used as the file format. The issue I am having is XE7 outputs the type TPointF differently than XE4 which causes an issue when trying to unmarshall.
This would not be an issue if I only had to handle opening files created with the new version but I have to support the old version files for at least a year. It looks like XE7 outputs all the possible fields in TPointF record (it is a variant record type)
Below is an example of the XE7 output
Using TJsonValue and TJsonMarshal:
{
"type":"tstMnfHole.TmnfHole",
"id":1,
"fields":
{
"fctrPoint":
[
[0.625,132.5],
0.625,
132.5
]
}
}
Using rest.json TJson.ObjectToJsonString(myHole)
{
"ctrPoint":
[
[0.625,132.5],
0.625,
132.5
]
}
Below is an example of the XE4 output
Using TJsonValue and TJsonMarshal:
{
"type":"tstMnfHole.TmnfHole",
"id":1,
"fields":
{
"fctrPoint":[0.625,132.5]
}
}
My questions are:
Is there a simple way to handle this with out having to override the default marshalling and create a custom converter/reverter so that the XE7 version outputs the same as XE4?
Is this worth posting on Embarcadero Quality Central?
small console test app for both XE4 and XE7.
XE7
program testPointf;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Types,
// rest.json,
data.dbxjsonReflect,
//data.dbxjson,
system.json,
tstMnfHole in 'tstMnfHole.pas';
var
myHole: TmnfHole;
valJson: TJSONValue;
Marshal: TJSONMarshal;
begin
try
{*** Create new test hole ***}
myHole := TmnfHole.Create(0.625, 132.5);
try
Marshal := TJSONMarshal.Create(TJSONConverter.Create);
try
valJson := Marshal.Marshal(myHole);
try
Writeln(valJson.ToString);
finally
valJson.Free;
end;
finally
Marshal.Free;
end;
finally
myHole.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
unit tstMnfHole;
interface
uses system.types;
type
TmnfHole = class(TObject)
//...
fctrPoint: TPointF;
constructor create; overload;
constructor create(thisCtrPoint: TPointF); overload;
constructor create(thisX, thisY: single); overload;
//...
end;
implementation
{ TmnfHole }
constructor TmnfHole.create;
begin
fctrPoint := TPointF.Create(0.75, 120.50);
end;
constructor TmnfHole.create(thisCtrPoint: TPointF);
begin
fctrPoint := TPointF.Create(thisCtrPoint.X, thisCtrPoint.Y);
end;
constructor TmnfHole.create(thisX, thisY: single);
begin
fctrPoint := TPointF.Create(thisX, thisY);
end;
end.
XE4
testPointf.dpr: replace system.json with data.dbxjson