FreePascal and JSON

Marcus Fernström
4 min readOct 13, 2019

--

JSON is the de facto standard for moving data around the web. It’s easy to use JSON with FreePascal but I still see people confused about how to go about it.

That’s why I decided to write this little crash course.

Everything we need comes bundled with Lazarus, no need to install extras.

I’m going to show you a very simple way to make a GET API call and access the JSON data, and then I’m going to show you how to generate a block of JSON and POST it to an API endpoint.

And we’re still just using the packages bundled with Lazarus.

We’ll start by making an API call to https://jsonplaceholder.typicode.com/users. This endpoint return 10 user records as an array of objects.

Those objects have both simple data like strings and a couple of nested objects. The data we get back looks like this:

[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
....

We’ll loop those records and output the id name address.street and company.name for each record.

The first program looks like this

program json_example;uses fpjson, jsonparser, fphttpclient;const url = 'https://jsonplaceholder.typicode.com/users';var
rawJson: AnsiString;
people: TJSONArray;
person: TJSONObject;
personEnum: TJSONEnum;
begin
// Get the JSON data
rawJson := TFPHTTPClient.SimpleGet(url);
// Convert to TJSONData and cast as TJSONArray
people := TJSONArray(GetJSON(rawJson));
// Loop using the TJSONEnumerator
for personEnum in people do begin
// Cast the enum value to person
person := TJSONObject(personEnum.Value);
// Output a few pieces of data as example.
WriteLn(person.FindPath('name').AsString);
WriteLn(person.FindPath('id').AsString);
WriteLn(person.FindPath('address.street').AsString);
WriteLn(person.FindPath('company.name').AsString);
WriteLn('');
end;

people.Free;
end.

This should all be pretty self-explanatory. We need fpjson and jsonparser to work with the data, and fphttpclient to make the api calls.

GetJSON returns TJSONData which we cast to a TJSONArray since we know that’s what’s being returned.

From there we use the TJSON Enumerator. Value contains the data and we just cast as a TJSONObject before we can get at the goodies.

With the Value now cast as a TJSONObject it’s very easy to access the data.

We’ll use FindPath with AsString to get the data as an AnsiString.

You have plenty of options for the types of data you can .As-- though. Here’s an excerpt of the .as<something> properties of TJSONData

Property AsString : TJSONStringType Read GetAsString Write SetAsString;
Property AsUnicodeString : TJSONUnicodeStringType Read GetAsUnicodeString Write SetAsUnicodeString;
Property AsFloat : TJSONFloat Read GetAsFloat Write SetAsFloat;
Property AsInteger : Integer Read GetAsInteger Write SetAsInteger;
Property AsInt64 : Int64 Read GetAsInt64 Write SetAsInt64;
Property AsQWord : QWord Read GetAsQWord Write SetAsQword;
Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean;

As you can see, it’s easy to consume JSON data in your FreePascal/Lazarus application.

This stock photo person agrees!

We’ll generate a JSON payload and POST it to https://jsonplaceholder.typicode.com/posts using a TFPHTTPClient.

The payload we’ll create will look like this, a couple of strings, an array, and an integer.

{
"title": "FPC is fun",
"body": "It is so much fun",
"friends": [
"Bob",
"Anne"
],
"userId": 1
}

Here’s the complete code for this example:

program json_example;uses classes, sysutils, fpjson, jsonparser, fphttpclient;const url = 'https://jsonplaceholder.typicode.com/posts';var
postJson: TJSONObject;
responseData: String;
begin
postJson := TJSONObject.Create;
postJson.Add('title', 'FPC is fun');
postJson.Add('body', 'It is so much fun');
postJson.Add('friends', TJSONArray.Create(['Bob', 'Anne']));
postJson.Add('userId', 1);
With TFPHttpClient.Create(Nil) do
try
AddHeader('Content-Type', 'application/json');
RequestBody := TStringStream.Create(postJson.AsJSON);
responseData := Post(url);
finally
Free;
end;
WriteLn(responseData);
end.

As you can see there’s not that much going on here, either!

We set up a TJSONObject and add our pieces of data directly to it, both simple and complex data can be created inline like this.

Next up we’re making an HTTP POST request to the API endpoint, and getting back a result-set like this, with the added id which is the newly created resource id on the server.

We specify a header Content-Type and set it to application/json , set the request body to be the serialized version of our TJSONData, make sure the response body is stored in responseData and Bob’s your uncle.

Here’s the response we get back from the server, it’s simply mirroring what we sent in and adding an “id” key.

{
"title": "FPC is fun",
"body": "It is so much fun",
"friends": [
"Bob",
"Anne"
],
"userId": 1,
"id": 101
}

And there you have it! A crash course intro to using JSON data with FreePascal and Lazarus.

--

--

Marcus Fernström

Sr. AppSec Engineer and Software Developer with a passion for open source. Historical Fencing instructor, and drinker of copious amounts of coffee and tea.