Skip to main content

Composer — dynamic editing

TJSONComposer (unit JsonFlow.Composer) provides an in-place, fluent API for building and mutating JSON structures. It implements IJSONComposer.

Building JSON from scratch

uses
JsonFlow.Composer,
JsonFlow.Interfaces;

var
LComposer: TJSONComposer;
begin
LComposer := TJSONComposer.Create;
try
LComposer
.BeginObject
.Add('name', 'Alice')
.Add('age', 28)
.Add('active', True)
.BeginArray('tags')
.Add('', 'dev')
.Add('', 'lead')
.EndArray
.EndObject;

WriteLn(LComposer.AsJSON);
finally
LComposer.Free;
end;
end;

Loading and mutating existing JSON

LComposer := TJSONComposer.Create;
try
LComposer.LoadJSON('{"user":{"name":"Bob","age":25},"tags":["dev"]}');

// Dot-notation path for nested access
LComposer.SetValue('user.age', 26);
LComposer.AddToArray('tags', 'lead');
LComposer.RemoveKey('user.name');

WriteLn(LComposer.AsJSON);
finally
LComposer.Free;
end;

Array manipulation

// Add single value
LComposer.AddToArray('items', 42);

// Add element (IJSONElement)
LComposer.AddToArray('items', LElement);

// Add multiple values
LComposer.AddToArray('items', TArray<Variant>.Create(1, 2, 3));

// Merge values into existing array
LComposer.MergeArray('items', TArray<Variant>.Create(4, 5));

// Remove by index
LComposer.RemoveFromArray('items', 0);

// Replace entire array content
LComposer.ReplaceArray('items', TArray<Variant>.Create(10, 20));

Nested object manipulation

// Add a named sub-object at path
LComposer.AddObject('user', 'address');

// Embed raw JSON at a key
LComposer.AddJSON('meta', '{"version":2}');

Convenience value methods

LComposer
.StringValue('city', 'Berlin')
.NumberValue('lat', 52.52)
.IntegerValue('zoom', 14)
.BooleanValue('visible', True)
.NullValue('extra')
.DateTimeValue('created', Now);

Callback-style nested builders

LComposer.ObjectValue('address',
procedure(const B: IJSONComposer)
begin
B.Add('street', 'Main St')
.Add('zip', '10115');
end
);

LComposer.ArrayValue('scores',
procedure(const B: IJSONComposer)
begin
B.Add('', 10).Add('', 20).Add('', 30);
end
);
// Navigate to a path for subsequent Add calls (context-aware)
LComposer.NavigateTo('user.address');
LComposer.GetCurrentPath; // returns 'user.address'
LComposer.GetContextInfo; // returns TContextInfo record

Debug mode

LComposer.EnableDebugMode(True);
// ... operations ...
for var LStep in LComposer.GetCompositionTrace do
WriteLn(LStep);

Output methods

MethodDescription
AsJSON(AIdent)Returns compact or indented JSON string
ToJSON(AIdent)Alias for AsJSON
ToElementReturns the root IJSONElement
GetRootReturns the root IJSONElement

Merging

// Merge another IJSONElement into the composer root
LComposer.Merge(LExtraElement);

Cloning and clearing

LClone := LComposer.Clone; // deep copy
LComposer.Clear; // reset to empty

TJSONNavigator — read-only path access

For read-only navigation, use TJSONNavigator directly:

uses
JsonFlow.Navigator;

var
LNav: TJSONNavigator;
begin
LNav := TJSONNavigator.Create(LComposer.GetRoot);
try
WriteLn(LNav.GetString('user.name'));
WriteLn(LNav.GetInteger('user.age'));
WriteLn(BoolToStr(LNav.GetBoolean('active'), True));
WriteLn(BoolToStr(LNav.IsNull('extra'), True));
finally
LNav.Free;
end;
end;

TJSONNavigator supports dot-notation and array index notation (tags[0]).