How to write a REST client with JSON in Delphi

 
Download example on GitHub
 
This tutorial represents a Delphi REST API Client with JSON. It makes a JSON request, which includes objects and object properties, sends this request to a Web service, and receives a JSON response. The example parses a received JSON response and extracts all included object properties.
 
The sources for both the clJsonSerializerBase and the clJsonSerializer units are free and can be downloaded from our GitHub repository
Also, please check out the following article, which describes how to use the JSON serialization classes in your code
 
See also:
 
The program implements two sample REST API commands: Create Job and Get Job.
 
An example of JSON request for the Create Job command:
 
//Create Job request
{
  "client_ref": "ABC123456",
  "customer_title": "Mr",
  "customer_firstname": "John",
  "customer_surname": "Smith",
  "customer_address": "123 The Lane,\n Sunnyvale",
  "customer_postcode": "ZZ1 1AA",
  "customer_telephone": "07711911911",
  "faults_client_description": "Issue with PROBLEM MIDDLE STITCHING IS MISSING (DIMPLE)",
  "clients_client": "Tony's furniture shop",
  "furniture_manufacturer": "Manufacturer Name",
  "furniture_model": "Model Name",
  "furniture_batch": "12334",
  "furniture_colour": "Red",
  "furniture_delivery_date": "2019-07-08",
  "general_instructions": "Ring customer ASAP"
}
 
Examples of JSON responses for the Create Job command:
 
//OK response
{
  "ism_reference": "STO6774"
}

//bad response
{
  "errors": {
    "code": "FIELD_INCOMPLETE",
    "invalid_fields": [
      "customer_surname",
      "customer_address",
      "customer_postcode"
    ]
  }
}
 
procedure TForm1.btnCreateJobClick(Sender: TObject);
var
  request, response, errors: TclJSONObject;
  invalid_fields: TclJSONArray;
  responseBody: TStringStream;
begin
  request := nil;
  response := nil;
  responseBody := nil;
  try
    memResult.Lines.Clear();

    request := TclJSONObject.Create();

    request.AddString('client_ref', client_ref.Text);
    request.AddString('customer_title', customer_title.Text);
    request.AddString('customer_firstname', customer_firstname.Text);
    request.AddString('customer_surname', customer_surname.Text);
    request.AddString('customer_postcode', customer_postcode.Text);
    request.AddString('customer_telephone', customer_telephone.Text);
    request.AddString('clients_client', 'Tony''s furniture shop');
    request.AddString('furniture_manufacturer', 'Manufacturer Name');
    request.AddString('furniture_model', 'Model Name');
    request.AddString('furniture_batch', '12334');
    request.AddString('furniture_colour', 'Red');
    request.AddString('furniture_delivery_date', '2019-07-08');

    clHttpRequest1.BuildJSONRequest(request);
    clHttpRequest1.Header.Authorization := FAuthorization;

    responseBody := TStringStream.Create();

    clHttp1.SilentHTTP := True; //allow receiving detailed error information
    clHttp1.Get('https://service.domain.com/jobs/add', clHttpRequest1, responseBody);

    response := TclJSONObject.ParseObject(responseBody.DataString);

    if (clHttp1.StatusCode <> 200) then
    begin
      errors := response.ObjectByName('errors');
      memResult.Lines.Add('code = ' + errors.ValueByName('code'));

      invalid_fields := errors.ArrayByName('invalid_fields');
      ShowArrayStrings('invalid_fields', invalid_fields);
    end else
    begin
      memResult.Lines.Add('ism_reference = ' + response.ValueByName('ism_reference'));
    end;
  finally
    responseBody.Free();
    response.Free();
    request.Free();
  end;
end;
 
procedure TForm1.btnGetJobDetailsClick(Sender: TObject);
var
  response, data, job, client, service_provider: TclJSONObject;
  errors: TclJSONObject;
  furniture, visits, job_history: TclJSONArray;
  responseBody: TStringStream;
begin
  response := nil;
  responseBody := nil;
  try
    memResult.Clear();

    clHttpRequest1.Clear();
    clHttpRequest1.Header.Authorization := FAuthorization;

    responseBody := TStringStream.Create();

    clHttp1.SilentHTTP := True; //allow receiving detailed error information
    clHttp1.Get('https://service.domain.com/jobs/get/' + ism_reference.Text,
      clHttpRequest1, responseBody);

    response := TclJSONObject.ParseObject(responseBody.DataString);

    data := response.ObjectByName('data');

    if (clHttp1.StatusCode <> 200) or (data = nil) then
    begin
      errors := response.ObjectByName('errors');
      memResult.Lines.Add('code = ' + errors.ValueByName('code'));
    end else
    begin
      job := data.ObjectByName('job');

      ShowObjectMembers('job', job);

      client := data.ObjectByName('client');
      ShowObjectMembers('client', client);

      service_provider := data.ObjectByName('service_provider');
      ShowObjectMembers('service_provider', service_provider);

      furniture := data.ArrayByName('furniture');
      ShowArrayMembers('furniture', furniture);

      visits := data.ArrayByName('visits');
      ShowArrayMembers('visits', visits);

      job_history := data.ArrayByName('job_history');
      ShowArrayMembers('job_history', job_history);
    end;
  finally
    responseBody.Free();
    response.Free();
  end;
end;

Add Feedback