Skip to content

InstantJSON ​

Unit: InstantJSONCategory: Brokers

Overview ​

The InstantJSON unit provides a file-based broker that stores objects as JSON files. Each object is saved as a separate JSON file in a folder structure organized by class name. This broker is ideal for prototyping, small datasets, configuration storage, and REST service integration.

Key Classes:

  • TJSONFilesAccessor - Connection component for JSON file access
  • TInstantJSONConnector - Connector for JSON broker
  • TInstantJSONBroker - Broker implementing JSON persistence
  • TInstantJSONConnectionDef - Connection definition for Connection Manager

TJSONFilesAccessor ​

Connection component that manages access to JSON files on the file system.

Inheritance: TCustomConnection → TJSONFilesAccessor

Key Properties ​

PropertyTypeDescription
RootFolderstringBase directory for JSON file storage
JSONFileFormatTJSONFileFormatxffUtf8 (default) or xffIso encoding
ConnectedBooleanConnection status

Events ​

EventTypeDescription
OnCustomLoadJSONFileTJSONFileOpenEventCustom JSON file loading
OnCustomSaveToJSONFileTJSONFileSaveEventCustom JSON file saving

Example Usage ​

pascal
var
  Accessor: TJSONFilesAccessor;
begin
  Accessor := TJSONFilesAccessor.Create(Self);
  Accessor.RootFolder := 'C:\MyApp\Data';
  Accessor.JSONFileFormat := xffUtf8;
  Accessor.Connected := True;
end;

File Organization ​

The accessor creates this folder structure:

RootFolder/
├── TContact/
│   ├── CONT001.json
│   ├── CONT002.json
│   └── CONT003.json
├── TCompany/
│   └── COMP001.json
└── TCategory/
    ├── CAT001.json
    └── CAT002.json

TInstantJSONConnector ​

Connector component integrating the JSON broker with InstantObjects.

Inheritance: TInstantConnectionBasedConnector → TInstantJSONConnector

Key Properties ​

PropertyTypeDescription
ConnectionTJSONFilesAccessorJSON files accessor
IsDefaultBooleanSet as default connector
BrokerClassTInstantBrokerClassReturns TInstantJSONBroker

Example Usage ​

pascal
var
  Connector: TInstantJSONConnector;
begin
  Connector := TInstantJSONConnector.Create(Self);
  Connector.Connection := JSONFilesAccessor;
  Connector.IsDefault := True;

  // Now all objects use JSON storage by default
  var Contact := TContact.Create;
  try
    Contact.Name := 'John Doe';
    Contact.Store;  // Saved to JSON file
  finally
    Contact.Free;
  end;
end;

TInstantJSONBroker ​

Broker implementing JSON file-based persistence.

Inheritance: TInstantNavigationalBroker → TInstantJSONBroker

Key Methods ​

pascal
// Implemented from base broker
procedure DisposeObject(AObject: TInstantObject; ConflictAction: TInstantConflictAction = caFail);
procedure RetrieveObject(AObject: TInstantObject; const AObjectId: string; ARefresh: Boolean = False);
procedure StoreObject(AObject: TInstantObject; ConflictAction: TInstantConflictAction = caFail);

JSON File Format ​

Each JSON file contains:

json
{
  "ClassName": "TContact",
  "Id": "CONT001",
  "_UpdateCount": 1,
  "_Name": "John Doe",
  "_Email": "john@example.com",
  "_Category": {
    "ReferenceObject": "TCategory#CAT001"
  },
  "_Phones": [
    {
      "_Number": "+1234567890",
      "_PhoneType": 0
    }
  ]
}

TJSONFileFormat ​

File encoding format enumeration.

pascal
type
  TJSONFileFormat = (
    xffUtf8,  // UTF-8 encoding (default, recommended)
    xffIso    // ISO-8859-1 encoding (legacy)
  );

Usage Patterns ​

Quick Start - Prototyping ​

pascal
// Design-time setup
procedure TMainForm.FormCreate(Sender: TObject);
begin
  // Drop components on form
  JSONFilesAccessor1.RootFolder := 'Data';
  JSONFilesAccessor1.Connected := True;

  JSONConnector1.Connection := JSONFilesAccessor1;
  JSONConnector1.IsDefault := True;

  // No database setup needed!
end;

// Create and store objects
var
  Contact: TContact;
begin
  Contact := TContact.Create;
  try
    Contact.Id := InstantGenerateId;
    Contact.Name := 'Jane Smith';
    Contact.Email := 'jane@example.com';
    Contact.Store;  // Saved to Data\TContact\[ID].json
  finally
    Contact.Free;
  end;
end;

Configuration Storage ​

pascal
// Application settings as persistent object
type
  TAppConfig = class(TInstantObject)
    {IOMETADATA stored 'CONFIG';
      Theme: String(20);
      Language: String(5);
      AutoSave: Boolean;}
    _Theme: TInstantString;
    _Language: TInstantString;
    _AutoSave: TInstantBoolean;
  published
    property Theme: string read GetTheme write SetTheme;
    property Language: string read GetLanguage write SetLanguage;
    property AutoSave: Boolean read GetAutoSave write SetAutoSave;
  end;

// Load or create config
var
  Config: TAppConfig;
begin
  Config := TAppConfig.Retrieve('DEFAULT', True);  // Create if missing
  try
    ApplyTheme(Config.Theme);
    SetLanguage(Config.Language);
  finally
    Config.Free;
  end;
end;

Data Export/Import ​

pascal
// Export data to JSON
procedure ExportToJSON(const ABackupFolder: string);
var
  Contacts: TObjectList;
begin
  // Configure JSON accessor
  JSONAccessor.RootFolder := ABackupFolder;
  JSONConnector.IsDefault := True;

  // Retrieve and store (exports to JSON)
  Contacts := TObjectList.Create(False);
  try
    TContact.RetrieveAll(Contacts);
    // Objects are already in JSON format
  finally
    Contacts.Free;
  end;
end;

// Import from JSON
procedure ImportFromJSON(const ASourceFolder: string);
begin
  // Just copy JSON files to active RootFolder
  CopyDirectory(ASourceFolder, JSONAccessor.RootFolder);
end;

Migration Between Brokers ​

pascal
// Migrate from JSON to SQL using InstantPump
var
  Pump: TInstantPump;
begin
  Pump := TInstantPump.Create(nil);
  try
    Pump.SourceConnector := JSONConnector;
    Pump.DestinationConnector := FireDACConnector;
    Pump.Execute;
  finally
    Pump.Free;
  end;
end;

Best Practices ​

  1. Use UTF-8 encoding - Better international character support
  2. Limit object count - Not suitable for thousands of objects per class
  3. Backup regularly - JSON files are plain text, easy to backup
  4. Use relative paths - Makes app portable
  5. Version control friendly - JSON format works well with Git
  6. Monitor file count - Performance degrades with many files
  7. Test concurrency - Update count prevents lost updates but doesn't lock files

Features and Limitations ​

Features ​

✅ No database setup required ✅ Human-readable format ✅ Easy debugging and inspection ✅ Version control friendly ✅ Cross-platform compatible ✅ Perfect for prototyping ✅ Optimistic locking via update count

Limitations ​

❌ No complex SQL queries ❌ No JOINs or aggregations ❌ Poor performance with large datasets ❌ No server-side indexing ❌ No transactions across multiple objects ❌ File system permissions required

Performance Considerations ​

  • Best for: < 1,000 objects total
  • Acceptable for: 1,000 - 10,000 objects
  • Not recommended for: > 10,000 objects

Optimization tips:

  • Keep classes in separate folders
  • Use SSDs for better I/O
  • Consider JSON broker for read-heavy scenarios
  • Migrate to SQL broker when scaling up

Troubleshooting ​

Problem: "Access denied" when saving

  • Solution: Check write permissions on RootFolder

Problem: Files not appearing

  • Solution: Verify RootFolder path exists and is correct

Problem: Corrupt JSON file

  • Solution: JSON files are text - open and manually fix if needed

Problem: Poor performance

  • Solution: Too many objects - migrate to FireDAC or other SQL broker

Problem: Lost updates in multi-user scenario

  • Solution: JSON broker uses file-level locking, implement application-level coordination

See Also ​

Released under Mozilla License, Version 2.0.