Networking, JSON & XML

For object serialization, FPC's fpjsonrtti (TJSONStreamer/TJSONDeStreamer) converts published properties to and from JSON.

40.1 Networking libraries

fphttpclient / fphttpserver (FCL) built-in HTTP client/server; HTTPS via opensslsockets (FPC 3.2+) fcl-net (ssockets) TCP/UDP sockets Synapse (Ararat) lightweight blocking sockets: HTTP, SMTP, FTP, SNMP, serial both (bundled with Delphi, OPM for Lazarus) large component suite: TIdHTTP, TIdTCPServer, TIdSMTP,...

System.Net.HttpClient (THTTPClient, TNetHTTPClient) uses the OS HTTP stack (no OpenSSL needed)

REST client library (TRESTClient, TRESTRequest) REST + JSON binding

fpWeb, Brook, Horse, mORMot 2, DMVCFramework, RAD Server web/REST server frameworks

40.2 HTTP GET + JSON parsing (Free Pascal)

program HttpJson;
{$mode objfpc}{$H+}
uses
  SysUtils, fphttpclient, opensslsockets, fpjson, jsonparser;

var
  Client: TFPHTTPClient;
  Body: string;
  Data: TJSONData;
  Obj: TJSONObject;
begin
  Client := TFPHTTPClient.Create(nil);
  try
    Client.AddHeader('User-Agent', 'pascal-course');
    Client.AllowRedirect := True;
    Body := Client.Get('https://httpbin.org/get?lang=pascal');
    Writeln('Status: ', Client.ResponseStatusCode);
  finally
    Client.Free;
  end;

  Data := GetJSON(Body);
  try
    Obj := Data as TJSONObject;
    Writeln('URL:  ', Obj.Get('url', ''));
    Writeln('lang: ', Obj.Objects['args'].Get('lang', ''));
  finally
    Data.Free;
  end;
end.

40.3 Building JSON (fpjson)

For object serialization, FPC's fpjsonrtti (TJSONStreamer/TJSONDeStreamer) converts published properties to and from JSON.

uses fpjson;
var
  Obj: TJSONObject;
begin
  Obj := TJSONObject.Create(['name', 'Ada', 'age', 36, 'active', True]);
  try
    Obj.Add('languages', TJSONArray.Create(['Pascal', 'Delphi']));
    Obj.Add('address', TJSONObject.Create(['city', 'London']));
    Writeln(Obj.AsJSON);         // compact
    Writeln(Obj.FormatJSON);     // pretty-printed
    Writeln(Obj.Integers['age'], ' ', Obj.Strings['name']);
  finally
    Obj.Free;                    // frees all children
  end;
end.

40.4 HTTP and JSON in Delphi

REST.Json.TJson.ObjectToJsonString(Obj) and TJson.JsonToObject<T>(S) serialize whole objects (fields), and System.JSON.Serializers offers attribute-driven serialization.

uses System.SysUtils, System.JSON, System.Net.HttpClient;

procedure Demo;
var
  Client: THTTPClient;
  Resp: IHTTPResponse;
  Obj: TJSONObject;
  V: TJSONValue;
begin
  Client := THTTPClient.Create;
  try
    Resp := Client.Get('https://httpbin.org/get?lang=pascal');
    Writeln(Resp.StatusCode);
    V := TJSONObject.ParseJSONValue(Resp.ContentAsString);
    try
      Writeln(V.GetValue<string>('args.lang'));    // path syntax
    finally
      V.Free;
    end;
  finally
    Client.Free;
  end;

  Obj := TJSONObject.Create;
  try
    Obj.AddPair('name', 'Ada');
    Obj.AddPair('age', TJSONNumber.Create(36));
    Obj.AddPair('languages', TJSONArray.Create.Add('Pascal').Add('Delphi'));
    Writeln(Obj.ToJSON);
  finally
    Obj.Free;
  end;
end;

40.5 Other clients

// Synapse (both compilers)
uses httpsend, Classes;
var SL: TStringList;
begin
  SL := TStringList.Create;
  try
    if HttpGetText('http://example.com/', SL) then Writeln(SL.Text);
  finally
    SL.Free;
  end;
end.

// Indy (both compilers); HTTPS also needs TIdSSLIOHandlerSocketOpenSSL and OpenSSL DLLs
uses IdHTTP;
var HTTP: TIdHTTP;
begin
  HTTP := TIdHTTP.Create(nil);
  try
    Writeln(HTTP.Get('http://example.com/'));
  finally
    HTTP.Free;
  end;
end.

40.6 XML

Free Pascal (units DOM, XMLRead, XMLWrite; Lazarus also has Laz2_DOM):

Delphi (Xml.XMLDoc, Xml.XMLIntf; console apps on Windows must call CoInitialize for the MSXML vendor):

Other options: OmniXML, NativeXml, FPC's SAX reader, and XPath (XPath unit in FPC, IDOMNodeSelect in Delphi).

uses DOM, XMLRead;
var
  Doc: TXMLDocument;
  Node: TDOMNode;
begin
  ReadXMLFile(Doc, 'books.xml');
  try
    Node := Doc.DocumentElement.FirstChild;
    while Assigned(Node) do
    begin
      if Node.NodeName = 'book' then
        Writeln(TDOMElement(Node).GetAttribute('title'));
      Node := Node.NextSibling;
    end;
  finally
    Doc.Free;
  end;
end.
uses Xml.XMLIntf, Xml.XMLDoc;
var
  Doc: IXMLDocument;
  I: Integer;
begin
  Doc := LoadXMLDocument('books.xml');
  for I := 0 to Doc.DocumentElement.ChildNodes.Count - 1 do
    Writeln(string(Doc.DocumentElement.ChildNodes[I].Attributes['title']));
end.