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 accessTInstantJSONConnector- Connector for JSON brokerTInstantJSONBroker- Broker implementing JSON persistenceTInstantJSONConnectionDef- Connection definition for Connection Manager
TJSONFilesAccessor
Connection component that manages access to JSON files on the file system.
Inheritance: TCustomConnection → TJSONFilesAccessor
Key Properties
| Property | Type | Description |
|---|---|---|
RootFolder | string | Base directory for JSON file storage |
JSONFileFormat | TJSONFileFormat | xffUtf8 (default) or xffIso encoding |
Connected | Boolean | Connection status |
Events
| Event | Type | Description |
|---|---|---|
OnCustomLoadJSONFile | TJSONFileOpenEvent | Custom JSON file loading |
OnCustomSaveToJSONFile | TJSONFileSaveEvent | Custom JSON file saving |
Example Usage
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.jsonTInstantJSONConnector
Connector component integrating the JSON broker with InstantObjects.
Inheritance: TInstantConnectionBasedConnector → TInstantJSONConnector
Key Properties
| Property | Type | Description |
|---|---|---|
Connection | TJSONFilesAccessor | JSON files accessor |
IsDefault | Boolean | Set as default connector |
BrokerClass | TInstantBrokerClass | Returns TInstantJSONBroker |
Example Usage
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
// 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:
{
"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.
type
TJSONFileFormat = (
xffUtf8, // UTF-8 encoding (default, recommended)
xffIso // ISO-8859-1 encoding (legacy)
);Usage Patterns
Quick Start - Prototyping
// 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
// 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
// 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
// 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
- Use UTF-8 encoding - Better international character support
- Limit object count - Not suitable for thousands of objects per class
- Backup regularly - JSON files are plain text, easy to backup
- Use relative paths - Makes app portable
- Version control friendly - JSON format works well with Git
- Monitor file count - Performance degrades with many files
- 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
- JSON Broker Guide - Detailed usage guide
- JSON Serialization - Enhanced with Neon
- InstantXML - Alternative file-based broker
- InstantFireDAC - SQL broker for scaling
- Connection Manager - Managing connections
