[Previous][Up][Next] Reference for unit 'JsonReader' (#fcl)

Using TJSONConsumerReader with IJSONConsumer interface

TJSONConsumerReader provides an alternative to event-based parsing by using the IJSONConsumer interface. Instead of assigning event handlers, you implement the interface methods to process JSON elements.

This approach provides a cleaner object-oriented design and can be easier to maintain for complex JSON processing logic.

The workflow involves:

  1. Create a class that implements IJSONConsumer
  2. Create a TJSONConsumerReader instance
  3. Assign your consumer to the Consumer property
  4. Call Execute to start parsing

Here's an example that builds a simple data structure from JSON:

program JSONConsumerDemo;

{$mode objfpc}{$H+}

uses
  Classes, SysUtils, jsonreader, Generics.Collections;

type
  TJSONDataExtractor = class(TInterfacedObject, IJSONConsumer)
  private
    FStack: TList<string>;
    FCurrentPath: string;
    FData: TStringList;
  public
    constructor Create;
    destructor Destroy; override;

    // IJSONConsumer interface
    procedure NullValue;
    procedure BooleanValue(const AValue: Boolean);
    procedure NumberValue(const AValue: string);
    procedure FloatValue(const AValue: Double);
    procedure Int64Value(const AValue: Int64);
    procedure QWordValue(const AValue: QWord);
    procedure IntegerValue(const AValue: Integer);
    procedure StringValue(const AValue: UTF8String);
    procedure KeyName(const AKey: UTF8String);
    procedure StartObject;
    procedure EndObject;
    procedure StartArray;
    procedure EndArray;

    property Data: TStringList read FData;
  end;

constructor TJSONDataExtractor.Create;
begin
  inherited Create;
  FStack := TList<string>.Create;
  FData := TStringList.Create;
end;

destructor TJSONDataExtractor.Destroy;
begin
  FStack.Free;
  FData.Free;
  inherited Destroy;
end;

procedure TJSONDataExtractor.KeyName(const AKey: UTF8String);
begin
  if FCurrentPath <> '' then
    FCurrentPath := FCurrentPath + '.' + AKey
  else
    FCurrentPath := AKey;
end;

procedure TJSONDataExtractor.StringValue(const AValue: UTF8String);
begin
  if FCurrentPath <> '' then
    FData.Values[FCurrentPath] := AValue;
  FCurrentPath := '';
end;

procedure TJSONDataExtractor.IntegerValue(const AValue: Integer);
begin
  if FCurrentPath <> '' then
    FData.Values[FCurrentPath] := IntToStr(AValue);
  FCurrentPath := '';
end;

procedure TJSONDataExtractor.BooleanValue(const AValue: Boolean);
begin
  if FCurrentPath <> '' then
    FData.Values[FCurrentPath] := BoolToStr(AValue, True);
  FCurrentPath := '';
end;

procedure TJSONDataExtractor.StartObject;
begin
  if FCurrentPath <> '' then
    FStack.Add(FCurrentPath);
end;

procedure TJSONDataExtractor.EndObject;
begin
  if FStack.Count > 0 then
  begin
    FCurrentPath := FStack[FStack.Count - 1];
    FStack.Delete(FStack.Count - 1);
  end
  else
    FCurrentPath := '';
end;

// Implement remaining interface methods
procedure TJSONDataExtractor.NullValue; begin FCurrentPath := ''; end;
procedure TJSONDataExtractor.NumberValue(const AValue: UTF8String); begin StringValue(AValue); end;
procedure TJSONDataExtractor.FloatValue(const AValue: Double); begin StringValue(FloatToStr(AValue)); end;
procedure TJSONDataExtractor.Int64Value(const AValue: Int64); begin StringValue(IntToStr(AValue)); end;
procedure TJSONDataExtractor.QWordValue(const AValue: QWord); begin StringValue(IntToStr(AValue)); end;
procedure TJSONDataExtractor.StartArray; begin end;
procedure TJSONDataExtractor.EndArray; begin end;

var
  Reader: TJSONConsumerReader;
  Extractor: TJSONDataExtractor;
  JSONData: string;
  i: Integer;
begin
  JSONData := '{"user": {"name": "Bob Jones", "age": 35, "active": true}, "settings": {"theme": "dark"}}';

  Extractor := TJSONDataExtractor.Create;
  Reader := TJSONConsumerReader.Create(JSONData, []);
  try
    Reader.Consumer := Extractor;
    Reader.Execute;

    Writeln('Extracted data:');
    or := 0 to Extractor.Data.Count - 1 do
      Writeln('  ', Extractor.Data[i]);

  finally
    Reader.Free;
    Extractor.Free;
  end;
end.

The consumer interface approach is beneficial when you need to:


Documentation generated on: Jan 27 2026