
Purpose: Framework Core Low-Level JSON Processing
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md
| Unit Name | Description | |
|---|---|---|
| mormot.core.base | Framework Core Shared Types and RTL-like Functions | |
| mormot.core.buffers | Framework Core Low-Level Memory Buffer Process | |
| mormot.core.data | Framework Core Low-Level Data Processing Functions | |
| mormot.core.datetime | Framework Core Low-Level Date and Time Support | |
| mormot.core.os | Framework Core Low-Level Wrappers to the Operating-System API | |
| mormot.core.rtti | Framework Core Low-Level Cross-Compiler RTTI Definitions | |
| mormot.core.text | Framework Core Low-Level Text Processing | |
| mormot.core.unicode | Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion | |
| mormot.core.variants | Framework Core Low-Level Variants / TDocVariant process |
| Objects | Description | |
|---|---|---|
| EJsonException | Exception raised by this unit, in relation to raw JSON process | |
| ESynDictionary | Exception raised during TSynDictionary process | |
| ISerializable | Abstract interface parent with common methods for JSON serialization | |
| TCollectionItemAutoCreateFields | Abstract TCollectionItem class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed | |
| TGetJsonField | Efficient JSON value parser / in-place decoder | |
| TInterfacedObjectAutoCreateFields | Abstract TInterfacedObject class, which will instantiate all its nested class published properties, then release them when freed | |
| TInterfacedSerializable | Abstract class parent with ISerializable methods for JSON serialization | |
| TInterfacedSerializableAutoCreateFields | Abstract ISerializable class parent with auto-create published fields | |
| TJsonParserContext | Efficient execution context of the JSON parser | |
| TJsonSaveContext | Internal stack-allocated structure for nested JSON serialization | |
| TJsonWriter | JSON-capable TTextWriter/TTextDateWriter inherited class | |
| TNameValuePUtf8Char | Store one name/value pair of raw UTF-8 content, from a JSON buffer | |
| TPersistentAutoCreateFields | Abstract TPersistent class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed | |
| TRttiJson | JSON-aware TRttiCustom class - used for global RttiCustom: TRttiCustomList | |
| TSynAutoCreateFields | Our own empowered TPersistentAutoCreateFields-like parent class | |
| TSynAutoCreateFieldsLocked | Adding locking methods to a TSynAutoCreateFields with virtual constructor | |
| TSynCache | Implement a cache of some key/value pairs, e.g. to improve reading speed | |
| TSynDictionary | Thread-safe dictionary to store some values from associated keys | |
| TSynJsonFileSettings | Abstract parent class able to store settings as JSON file | |
| TSynNameValue | Pseudo-class used to store Name/Value RawUtf8 pairs | |
| TSynNameValueItem | Store one Name/Value pair, as used by TSynNameValue class | |
| TSynPersistentStoreJson | Implement binary persistence and JSON serialization (not deserialization) |
EJsonException = class(ESynException)
Exception raised by this unit, in relation to raw JSON process
TGetJsonField = object(TObject)
Efficient JSON value parser / in-place decoder
- as used by JsonDecode() and all internal JSON functions
EndOfObject: AnsiChar;
The ',' ':' or '}' separator just after the Value
- may have been overwritten with a #0 termination in the input buffer
Json: PUtf8Char;
Input/output JSON parsing buffer address
Value: PUtf8Char;
In-place output parsed JSON value, unescaped and #0 terminated
- see associated WasString to find out its actual type
ValueLen: integer;
In-place output parsed JSON value length
WasString: boolean;
Set if the value was actually a JSON string
- "strings" are decoded as 'strings', with WasString=true, properly JSON unescaped (e.g. any \u0123 pattern would be converted into UTF-8 content)
- numbers are decoded as text, e.g. '1.234', with WasString=false
- null is decoded as Value=nil and WasString=false
- true/false are decoded as 'true'/'false' with WasString=false
function GetJsonInt64: Int64;
Decode a JSON 64-bit integer value from an UTF-8 encoded text buffer
procedure GetJsonField;
Decode a JSON field value in-place from an UTF-8 encoded text buffer
- warning: will decode in the Json buffer memory itself (no memory copy nor allocation), for faster process - so take care that it is not shared
- Value/ValueLen/WasString is set with the parsed value
- EndOfObject is set to the JSON ending char (',' ':' or '}' e.g.)
- Json points to the next field to be decoded, or nil on parsing error
procedure GetJsonFieldOrObjectOrArray( HandleValuesAsObjectOrArray: boolean = true; NormalizeBoolean: boolean = true);
Decode a JSON content from an UTF-8 encoded buffer
- GetJsonField will only handle JSON "strings" or numbers - if HandleValuesAsObjectOrArray is TRUE, this function will process JSON { objects } or [ arrays ] and add a #0 at the end of it
- warning: will decode in the Json buffer memory itself (no memory allocation or copy), for faster process - so take care that it is not shared
- Value/ValueLen/WasString is set with the parsed JSON value
- EndOfObject is set to the JSON ending char (',' ':' or '}' e.g.)
- Json points to the next value to be decoded, or nil on parsing error
procedure GetJsonValue(var Text: RawUtf8);
Decode a JSON field value in-place into a RawUtf8 string
TJsonWriter = class(TTextDateWriter)
JSON-capable TTextWriter/TTextDateWriter inherited class
- in addition to TTextWriter/TTextDateWriter, will handle JSON serialization of any kind of value, including records, classes or arrays
destructor Destroy; override;
Release all internal structures
function AddDynArrayJson(Value: pointer; Info: TRttiCustom; WriteOptions: TTextWriterWriteObjectOptions = []): PtrInt; overload;
Append a dynamic array content as UTF-8 encoded JSON array
- returns the array element size
function AddJsonReformat(Json: PUtf8Char; Format: TTextWriterJsonFormat; EndOfObject: PUtf8Char): PUtf8Char; override;
Append a JSON value, array or document, in a specified format
- this overriden version will properly handle JSON escape
function AddJsonToXML(Json: PUtf8Char; ArrayName: PUtf8Char = nil; EndOfObject: PUtf8Char = nil): PUtf8Char;
Append a JSON value, array or document as simple XML content
- you can use JsonBufferToXML() and JsonToXML() functions as wrappers
- this method is called recursively to handle all kind of JSON values
- WARNING: the JSON buffer is decoded in-place, so will be changed
- returns the end of the current JSON converted level, or nil if the supplied content was not correct JSON
function AddRecordJson(Value: pointer; RecordInfo: PRttiInfo; WriteOptions: TTextWriterWriteObjectOptions = []): PtrInt;
Append a record content as UTF-8 encoded JSON or custom serialization
- default serialization will use Base64 encoded binary stream, or a custom serialization, in case of a previous registration via TRttiJson.RegisterCustomSerializer() class method - from a dynamic array handling this kind of records, or directly from TypeInfo() of the record
- by default, custom serializers defined via RegisterCustomSerializer() would write enumerates and sets as integer numbers, unless twoEnumSetsAsTextInRecord or twoEnumSetsAsBooleanInRecord is set in the instance CustomOptions
- returns the element size
function GetTempJsonWriter: TJsonWriter;
Gives access to a temporary TJsonWriter
- returned instance is owned by this TJsonWriter, and voided
- may be used to escape some JSON espaced value (i.e. escape it twice), in conjunction with AddJsonEscape(Source: TJsonWriter)
procedure Add(P: PUtf8Char; Len: PtrInt; Escape: TTextWriterKind); override;
Write some #0 ended UTF-8 text, according to the specified format
- if Escape is a constant, consider calling directly AddNoJsonEscape, AddJsonEscape or AddOnSameLine methods
procedure Add(P: PUtf8Char; Escape: TTextWriterKind); override;
Write some #0 ended UTF-8 text, according to the specified format
- if Escape is a constant, consider calling directly AddNoJsonEscape, AddJsonEscape or AddOnSameLine methods
procedure Add(const Values: array of const); overload;
Append some values at once
- text values (e.g. RawUtf8) will be escaped as JSON by default
procedure Add(const Format: RawUtf8; const Values: array of const; Escape: TTextWriterKind = twNone; WriteObjectOptions: TTextWriterWriteObjectOptions = [woFullExpand]); override;
Append strings or integers with a specified format
- this overriden version will properly handle JSON escape
- % = #37 marks a string, integer, floating-point, or class parameter to be appended as text (e.g. class name)
- note that due to a limitation of the "array of const" format, cardinal values should be type-casted to Int64() - otherwise the integer mapped value will be transmitted, therefore wrongly
procedure Add(const Values: array of const; Escape: TTextWriterKind); overload;
Append some values at once with custom escaping
procedure Add(const V: TVarRec; Escape: TTextWriterKind = twNone; WriteObjectOptions: TTextWriterWriteObjectOptions = [woFullExpand]); overload;
Append an open array constant value to the buffer
- "" won't be added for string values
- string values may be escaped, depending on the supplied parameter
- very fast (avoid most temporary storage)
procedure AddAnsiString(const s: AnsiString; Escape: TTextWriterKind); overload;
Append some UTF-8 encoded chars to the buffer, from the main AnsiString type
- use the current system code page for AnsiString parameter
procedure AddAnyAnsiBuffer(P: PAnsiChar; Len: PtrInt; Escape: TTextWriterKind; CodePage: integer);
Append some UTF-8 encoded chars to the buffer, from any Ansi buffer
- the codepage should be specified, e.g. CP_UTF8, CP_RAWBYTESTRING, CP_WINANSI, or any version supported by the Operating System
- if codepage is 0, the current CurrentAnsiConvert.CodePage would be used
- will use TSynAnsiConvert to perform the conversion to UTF-8
procedure AddAnyAnsiString(const s: RawByteString; Escape: TTextWriterKind; CodePage: integer = -1);
Append some UTF-8 encoded chars to the buffer, from any AnsiString value
- if CodePage is left to its default value of -1, it will assume CurrentAnsiConvert.CodePage prior to Delphi 2009, but newer UNICODE versions of Delphi will retrieve the code page from string
- if CodePage is defined to a >= 0 value, the encoding will take place
procedure AddCRAndIndent; override;
Append CR+LF (#13#10) chars and #9 indentation
- will also flush any fBlockComment
procedure AddCsvConst(const Values: array of const);
Append an array of const as CSV of JSON values
procedure AddCsvUtf8(const Values: array of RawUtf8);
Append an array of RawUtf8 as CSV of JSON strings
procedure AddDynArrayJson(var DynArray: TDynArray; WriteOptions: TTextWriterWriteObjectOptions = []); overload;
Append a dynamic array content as UTF-8 encoded JSON array
- typical content could be
'[1,2,3,4]' or '["\uFFF0base64encodedbinary"]'
procedure AddDynArrayJson(var DynArray: TDynArrayHashed; WriteOptions: TTextWriterWriteObjectOptions = []); overload;
Append a dynamic array content as UTF-8 encoded JSON array
- expect a dynamic array TDynArrayHashed wrapper as incoming parameter
procedure AddDynArrayJsonAsString(aTypeInfo: PRttiInfo; var aValue; WriteOptions: TTextWriterWriteObjectOptions = []);
Same as AddDynArrayJson(), but will double all internal " and bound with "
- this implementation will avoid most memory allocations
procedure AddJson(const Format: RawUtf8; const Args, Params: array of const);
Encode the supplied (extended) JSON content, with parameters, as an UTF-8 valid JSON object content
- in addition to the JSON RFC specification strict mode, this method will handle some BSON-like extensions, e.g. unquoted field names:
aWriter.AddJson('{id:?,%:{name:?,birthyear:?}}',['doc'],[10,'John',1982]);
- you can use nested _Obj() / _Arr() instances
aWriter.AddJson('{%:{$in:[?,?]}}',['type'],['food','snack']); aWriter.AddJson('{type:{$in:?}}',[],[_Arr(['food','snack'])]); // which are the same as: aWriter.AddShort('{"type":{"$in":["food","snack"]}}');
- if the mormot.db.nosql.bson unit is used in the application, the MongoDB Shell syntax will also be recognized to create TBsonVariant, like
new Date() ObjectId() MinKey MaxKey /<jRegex>/<jOptions>
see @http://docs.mongodb.org/manual/reference/mongodb-extended-json
aWriter.AddJson('{name:?,field:/%/i}',['acme.*corp'],['John'])) // will write '{"name":"John","field":{"$regex":"acme.*corp","$options":"i"}}'
- will call internally _JsonFastFmt() to create a temporary TDocVariant with all its features - so is slightly slower than other AddJson* methods
procedure AddJsonArraysAsJsonObject(keys, values: PUtf8Char);
Append two JSON arrays of keys and values as one JSON object
- i.e. makes the following transformation:
[key1,key2...] + [value1,value2...] -> {key1:value1,key2,value2...}- this method won't allocate any memory during its process, nor modify the keys and values input buffers
- is the reverse of the JsonObjectAsJsonArrays() function
- used e.g. by TSynDictionary.SaveToJson
procedure AddJsonEscape(P: pointer; Len: PtrInt = 0); overload;
Append some UTF-8 encoded chars to the buffer
- escapes chars according to the JSON RFC
- if Len is 0, writing will stop at #0 (default Len = 0 is slightly faster than specifying Len>0 if you are sure P is zero-ended - e.g. from RawUtf8)
procedure AddJsonEscape( const NameValuePairs: array of const); overload;
Encode the supplied data as an UTF-8 valid JSON object content
- data must be supplied two by two, as Name,Value pairs, e.g.
aWriter.AddJsonEscape(['name','John','year',1972]);
will append to the buffer:
'{"name":"John","year":1972}'- or you can specify nested arrays or objects with '['..']' or '{'..'}':
aWriter.AddJsonEscape(['doc','{','name','John','ab','[','a','b']','}','id',123]);
will append to the buffer:
'{"doc":{"name":"John","abc":["a","b"]},"id":123}'- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
- you can pass nil as parameter for a null JSON value
procedure AddJsonEscape(const V: TVarRec); overload;
Append an open array constant value to the buffer
- "" will be added if necessary
- escapes chars according to the JSON RFC
- very fast (avoid most temporary storage)
procedure AddJsonEscape(Source: TJsonWriter); overload;
Flush a supplied TJsonWriter, and write pending data as JSON escaped text
- may be used with InternalJsonWriter, as a faster alternative to
AddJsonEscape(pointer(fInternalJsonWriter.Text),0);
procedure AddJsonEscapeAnsiString(const s: AnsiString);
Append some UTF-8 encoded chars to the buffer, from the main AnsiString type
- escapes chars according to the JSON RFC
procedure AddJsonEscapeString(const s: string);
Append some UTF-8 encoded chars to the buffer, from a RTL string type
- faster than AddJsonEscape(pointer(StringToUtf8(string))
- escapes chars according to the JSON RFC
procedure AddJsonEscapeW(P: PWord; Len: PtrInt = 0);
Append some Unicode encoded chars to the buffer
- if Len is 0, Len is calculated from zero-ended widechar
- escapes chars according to the JSON RFC
procedure AddJsonString(const Text: RawUtf8);
Append a UTF-8 JSON string, JSON escaped between double quotes
- "" will always be added, before calling AddJsonEscape()
procedure AddNoJsonEscape(Source: TJsonWriter); overload;
Flush a supplied TJsonWriter, and write pending data as JSON escaped text
- may be used with InternalJsonWriter, as a faster alternative to
AddNoJsonEscapeUtf8(Source.Text);
procedure AddNoJsonEscapeForcedNoUnicode(P: PUtf8Char; Len: PtrInt);
Append a UTF-8 encoded JSON buffer without any \u#### Unicode escape
- i.e. \u#### patterns will be converted into pure UTF-8 output
- as used for jsonNoEscapeUnicode transformation
procedure AddNoJsonEscapeForcedUnicode(P: PUtf8Char; Len: PtrInt);
Append a UTF-8 already encoded JSON buffer forcing Unicode escape
- don't escapes chars according to the JSON RFC but convert any 8-bit UTF-8 values as their UTF-16 \u#### escaped content
- i.e. generate a pure ASCII output with no UTF-8 encoding involved
- used for jsonEscapeUnicode to follow python default json.dumps() layout
procedure AddPropJsonString(const PropName: ShortString; const Text: RawUtf8);
Append a JSON field name, followed by an escaped UTF-8 JSON String and a comma (',')
procedure AddQuotedStringAsJson(const QuotedString: RawUtf8);
Append a quoted string as JSON, with in-place decoding
- if QuotedString does not start with ' or ", it will written directly (i.e. expects to be a number, or null/true/false constants)
- as used e.g. by TJsonObjectDecoder.EncodeAsJson method and JsonEncodeNameSQLValue() function
procedure AddRttiCustomJson(Value: pointer; RttiCustom: TObject; Escape: TTextWriterKind; WriteOptions: TTextWriterWriteObjectOptions);
Append complex types as JSON content using TRttiCustom
- called e.g. by TJsonWriter.AddVariant() for varAny / TRttiVarData
procedure AddText(const Text: RawByteString; Escape: TTextWriterKind = twJsonEscape);
Append UTF-8 content as text
- Text CodePage will be used (if possible) - assume RawUtf8 otherwise
- will properly handle JSON escape between two " double quotes
procedure AddTextW(P: PWord; Escape: TTextWriterKind = twJsonEscape);
Append UTF-16 content as text
- P should be a #0 terminated PWideChar buffer
- will properly handle JSON escape between two " double quotes
procedure AddTypedJson(Value, TypeInfo: pointer; WriteOptions: TTextWriterWriteObjectOptions = []); override;
Append complex types as JSON content using raw TypeInfo()
- handle rkClass as WriteObject, rkEnumeration/rkSet with proper options, rkRecord, rkDynArray or rkVariant using proper JSON serialization
- other types will append 'null'
procedure AddVariant(const Value: variant; Escape: TTextWriterKind = twJsonEscape; WriteOptions: TTextWriterWriteObjectOptions = []); override;
Append a variant content as number or string
- this overriden version will properly handle JSON escape
- properly handle varAny from TRttiCustomProp.GetRttiVarData
procedure AddVoidRecordJson(RecordInfo: PRttiInfo; WriteOptions: TTextWriterWriteObjectOptions = []);
Append a void record content as UTF-8 encoded JSON or custom serialization
- this method will first create a void record (i.e. filled with #0 bytes) then save its content with default or custom serialization
procedure AddW(P: PWord; Len: PtrInt; Escape: TTextWriterKind);
Write some #0 ended Unicode text as UTF-8, according to the specified format
- if Escape is a constant, consider calling directly AddNoJsonEscapeW, AddJsonEscapeW or AddOnSameLineW methods
procedure BinarySaveBase64(Data: pointer; Info: PRttiInfo; Kinds: TRttiKinds; withMagic: boolean; withCrc: boolean = false);
Write some binary-saved data with Base64 encoding
- if withMagic is TRUE, will write as '"\uFFF0base64encodedbinary"'
- is a wrapper around BinarySave() and WrBase64()
procedure BlockAfterItem(Options: TTextWriterWriteObjectOptions);
Append ',' with proper indentation
- warning: this will break CancelLastComma, since CRLF+tabs are added
procedure BlockBegin(Starter: AnsiChar; Options: TTextWriterWriteObjectOptions);
Append '[' or '{' with proper indentation
procedure BlockEnd(Stopper: AnsiChar; Options: TTextWriterWriteObjectOptions);
Append ']' or '}' with proper indentation
procedure WrBase64(P: PAnsiChar; Len: PtrUInt; withMagic: boolean); override;
Write some data Base64 encoded
- if withMagic is TRUE, will write as '"\uFFF0base64encodedbinary"'
procedure WriteObject(Value: TObject; WriteOptions: TTextWriterWriteObjectOptions = [woDontStoreDefault]); override;
Serialize as JSON the given object
procedure WriteObjectAsString(Value: TObject; Options: TTextWriterWriteObjectOptions = [woDontStoreDefault]);
Same as WriteObject(), but will double all internal " and bound with "
- this implementation will avoid most memory allocations
procedure WriteObjectPropNameHumanReadable(PropName: PUtf8Char; PropNameLen: PtrInt);
Used internally by WriteObject() when serializing a published property
- will call AddCRAndIndent then append "PropName":
procedure WriteObjectPropNameShort(const PropName: ShortString; Options: TTextWriterWriteObjectOptions);
Used internally by WriteObject() when serializing a published property
- will call AddCRAndIndent then append "PropName":
TSynNameValueItem = record
Store one Name/Value pair, as used by TSynNameValue class
Name: RawUtf8;
The name of the Name/Value pair
- this property is hashed by TSynNameValue for fast retrieval
Tag: PtrInt;
Any associated pointer or numerical value
Value: RawUtf8;
The value of the Name/Value pair
TSynNameValue = object(TObject)
Pseudo-class used to store Name/Value RawUtf8 pairs
- use internally a TDynArrayHashed instance for fast retrieval
- is therefore faster than TRawUtf8List
- is defined as an object, not as a class: you can use this in any class, without the need to destroy the content
- Delphi "object" is buggy on stack -> also defined as record with methods
Count: integer;
The number of Name/Value pairs
DynArray: TDynArrayHashed;
Low-level access to the internal storage hasher
List: TSynNameValueItemDynArray;
The internal Name/Value storage
function AsCsv(const KeySeparator: RawUtf8 = '='; const ValueSeparator: RawUtf8 = #13#10; const IgnoreKey: RawUtf8 = ''): RawUtf8;
Returns all values, as CSV or INI content
function AsDocVariant(ExtendedJson: boolean = false; ValueAsString: boolean = true): variant; overload;
Compute a TDocVariant document from the stored values
function AsJson: RawUtf8;
Returns all values as a JSON object of string fields
function Delete(const aName: RawUtf8): boolean;
Search for a Name, and delete its entry in the List if it exists
function DeleteByValue(const aValue: RawUtf8; Limit: integer = 1): integer;
Search for a Value, and delete its entry in the List if it exists
- returns the number of deleted entries
- you may search for more than one match, by setting a >1 Limit value
function Find(const aName: RawUtf8): PtrInt;
Search for a Name, return the index in List
- using fast O(1) hash algoritm
function FindByValue(const aValue: RawUtf8): PtrInt;
Search for a Value, return the index in List
- using O(n) brute force algoritm with case-sensitive aValue search
function FindStart(const aUpperName: RawUtf8): PtrInt;
Search for the first chars of a Name, return the index in List
- using O(n) calls of IdemPChar() function
- here aUpperName should be already uppercase, as expected by IdemPChar()
function InitFromJson(Json: PUtf8Char; aCaseSensitive: boolean = false): boolean;
Reset content, then add all fields from an JSON object
- will first call Init() to initialize the internal array
- then parse the incoming JSON object, storing all its field values as RawUtf8, and returning TRUE if the supplied content is correct
- warning: the supplied JSON buffer will be decoded and modified in-place
function Initialized: boolean;
Returns true if the Init() method has been called
function MergeDocVariant(var DocVariant: variant; ValueAsString: boolean; ChangedProps: PVariant = nil; ExtendedJson: boolean = false; AllowVarDouble: boolean = false): integer;
Merge the stored values into a TDocVariant document
- existing properties would be updated, then new values will be added to the supplied TDocVariant instance, ready to be serialized as a JSON object
- if ValueAsString is TRUE, values would be stored as string
- if ValueAsString is FALSE, numerical values would be identified by IsString() and stored as such in the resulting TDocVariant
- if you let ChangedProps point to a TDocVariantData, it would contain an object with the stored values, just like AsDocVariant
- returns the number of updated values in the TDocVariant, 0 if no value was changed
function Value(const aName: RawUtf8; const aDefaultValue: RawUtf8 = ''): RawUtf8;
Search for a Name, return the associated Value as a UTF-8 string
function ValueBool(const aName: RawUtf8): boolean;
Search for a Name, return the associated Value as boolean
- returns true only if the value is exactly '1' / 'true'
function ValueEnum(const aName: RawUtf8; aEnumTypeInfo: PRttiInfo; out aEnum; aEnumDefault: PtrUInt = 0): boolean; overload;
Search for a Name, return the associated Value as an enumerate
- returns true and set aEnum if aName was found, and associated value matched an aEnumTypeInfo item
- returns false if no match was found
function ValueInt(const aName: RawUtf8; const aDefaultValue: Int64 = 0): Int64;
Search for a Name, return the associated Value as integer
function ValueVariantOrNull(const aName: RawUtf8): variant;
Search for a Name, return the associated Value as variant
- returns null if the name was not found
procedure Add(const aName, aValue: RawUtf8; aTag: PtrInt = 0);
Add an element to the array
- if aName already exists, its associated Value will be updated
procedure AsDocVariant(out DocVariant: variant; ExtendedJson: boolean = false; ValueAsString: boolean = true; AllowVarDouble: boolean = false); overload;
Compute a TDocVariant document from the stored values
- output variant will be reset and filled as a TDocVariant instance, ready to be serialized as a JSON object
- if there is no value stored (i.e. Count=0), set null
procedure AsNameValues(out Names, Values: TRawUtf8DynArray);
Fill the supplied two arrays of RawUtf8 with the stored values
procedure Init(aCaseSensitive: boolean);
Initialize the storage
- will also reset the internal List[] and the internal hash array
procedure InitFromCsv(Csv: PUtf8Char; NameValueSep: AnsiChar = '='; ItemSep: AnsiChar = #10);
Reset content, then add all name=value; CSV pairs
- will first call Init(false) to initialize the internal array
- if ItemSep=#10, then any kind of line feed (CRLF or LF) will be handled
procedure InitFromIniSection(Section: PUtf8Char; const OnTheFlyConvert: TOnSynNameValueConvertRawUtf8 = nil; const OnAdd: TOnSynNameValueNotify = nil);
Reset content, then add all name=value pairs from a supplied .ini file section content
- will first call Init(false) to initialize the internal array
- Section can be retrieved e.g. via FindSectionFirstLine()
procedure InitFromNamesValues(const Names, Values: array of RawUtf8);
Reset content, then add all name, value pairs
- will first call Init(false) to initialize the internal array
procedure SetBlobDataPtr(aValue, aValueMax: pointer);
Can be used to set all data from one BLOB memory buffer
property BlobData: RawByteString read GetBlobData write SetBlobData;
Can be used to set or retrieve all stored data as one BLOB content
property Bool[const aName: RawUtf8]: boolean read ValueBool;
Search for a Name, return the associated Value as boolean
- returns true if aName stores '1' / 'true' as associated value
property Int[const aName: RawUtf8]: Int64 read GetInt;
Search for a Name, return the associated Value as integer
- returns 0 if aName is not found, or not a valid Int64 in the stored keys
property OnAfterAdd: TOnSynNameValueNotify read fOnAdd write fOnAdd;
Event triggerred after an item has just been added to the list
property Str[const aName: RawUtf8]: RawUtf8 read GetStr;
Search for a Name, return the associated Value as a UTF-8 string
- returns '' if aName is not found in the stored keys
TSynCache = class(TSynPersistent)
Implement a cache of some key/value pairs, e.g. to improve reading speed
- used e.g. by TSqlDataBase for caching the SELECT statements results in an internal JSON format (which is faster than a query to the SQLite3 engine)
- internally make use of an efficient hashing algorithm for fast response (i.e. TSynNameValue will use the TDynArrayHashed wrapper mechanism)
constructor Create(aMaxCacheRamUsed: cardinal = 16 shl 20; aCaseSensitive: boolean = false; aTimeoutSeconds: cardinal = 0); reintroduce;
Call Reset after TimeoutSeconds initialize the internal storage
- aMaxCacheRamUsed can set the maximum RAM to be used for values, in bytes (default is 16 MB), after which the cache is flushed
- by default, key search is done case-insensitively, but you can specify another option here
- by default, there is no timeout period, but you may specify a number of seconds of inactivity (i.e. no Add call) after which the cache is flushed
function AddOrUpdate(const aKey, aValue: RawUtf8; aTag: PtrInt): boolean;
Add a Key/Value pair in the cache entries
- returns true if aKey was not existing yet, and aValue has been stored
- returns false if aKey did already exist in the internal cache, and its entry has been updated with the supplied aValue/aTag
- this method is thread-safe, using the Safe R/W locker of this instance
function Find(const aKey: RawUtf8; aResultTag: PPtrInt = nil): RawUtf8;
Find a Key in the cache entries
- return '' if nothing found: you may call Add() just after to insert the expected value in the cache
- return the associated Value otherwise, and the associated integer tag if aResultTag address is supplied
- this method is thread-safe, using the Safe R/W locker of this instance
function Reset: boolean;
Called after a write access to the database to flush the cache
- set Count to 0
- release all cache memory
- returns TRUE if was flushed, i.e. if there was something in cache
- this method is thread-safe, using the Safe R/W locker of this instance
property Count: integer read fNameValue.Count;
Number of entries in the cache
property MaxRamUsed: cardinal read fMaxRamUsed;
The maximum RAM to be used for values, in bytes
- the cache is flushed when ValueSize reaches this limit
- default is 16 MB (16 shl 20)
property RamUsed: cardinal read fRamUsed;
The current global size of Values in RAM cache, in bytes
property Safe: TRWLock read fSafe;
Access to the internal R/W locker, for thread-safe process
- Find/AddOrUpdate methods are protected by this R/W lock
property TimeoutSeconds: cardinal read fTimeoutSeconds;
After how many seconds betwen Add() calls the cache should be flushed
- equals 0 by default, meaning no time out
TSynPersistentStoreJson = class(TSynPersistentStore)
Implement binary persistence and JSON serialization (not deserialization)
function SaveToJson(reformat: TTextWriterJsonFormat = jsonCompact): RawUtf8;
Serialize this instance as a JSON object
ESynDictionary = class(ESynException)
Exception raised during TSynDictionary process
TSynDictionary = class(TSynLocked)
Thread-safe dictionary to store some values from associated keys
- will maintain a dynamic array of values, associated with a hash table for the keys, so that setting or retrieving values would be O(1)
- thread-safe by default, since most methods are protected by a TSynLocker; use the ThreadUse option to tune thread-safety (e.g. disable or use a TRWLock)
- TDynArray is a wrapper which does not store anything, whereas this class actually stores both keys and values, and provide convenient methods to access the stored data, including JSON serialization and binary storage
- consider IKeyValue<> from mormot.core.collections.pas, for more robust generics-based code where TKey/TValue are propagated to all methods
constructor Create(aKeyTypeInfo, aValueTypeInfo: PRttiInfo; aKeyCaseInsensitive: boolean = false; aTimeoutSeconds: cardinal = 0; aCompressAlgo: TAlgoCompress = nil; aHasher: THasher = nil); reintroduce; virtual;
Initialize the dictionary storage, specifying dynamic array keys/values
- aKeyTypeInfo should be a dynamic array TypeInfo() RTTI pointer, which would store the keys within this TSynDictionary instance
- aValueTypeInfo should be a dynamic array TypeInfo() RTTI pointer, which would store the values within this TSynDictionary instance
- by default, string keys would be searched following exact case, unless aKeyCaseInsensitive is TRUE
- you can set an optional timeout period, in seconds - you should call DeleteDeprecated periodically to search for deprecated items
destructor Destroy; override;
Finalize the storage
- would release all internal stored values
function Add(const aKey, aValue): PtrInt;
Try to add a value associated with a primary key
- returns the index of the inserted item, -1 if aKey is already existing
- this method is thread-safe, since it will lock the instance
function AddInArray(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Add aArrayValue item within a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, then use TDynArray.Add to add aArrayValue to the associated dynamic array
- returns FALSE if Values is not a tkDynArray, or if aKey was not found
- this method is thread-safe, since it will lock the instance
function AddInArrayForced(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Add aArrayValue item within a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, create the entry if not found, then use TDynArray.Add to add aArrayValue to the associated dynamic array
- returns FALSE if Values is not a tkDynArray
- this method is thread-safe, since it will lock the instance
function AddOnceInArray(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Add once aArrayValue within a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, then use TDynArray.FindAndAddIfNotExisting to add once aArrayValue to the associated dynamic array
- returns FALSE if Values is not a tkDynArray, or if aKey was not found
- this method is thread-safe, since it will lock the instance
function AddOrUpdate(const aKey, aValue): PtrInt;
Store a value associated with a primary key
- returns the index of the matching item
- if aKey does not exist, a new entry is added
- if aKey does exist, the existing entry is overriden with aValue
- this method is thread-safe, since it will lock the instance
function Clear(const aKey): PtrInt;
Clear the value associated via aKey
- does not delete the entry, but reset its value
- returns the index of the matching item, -1 if aKey was not found
- this method is thread-safe, since it will lock the instance
function Count: integer;
Returns how many items are currently stored in this dictionary
- this method is NOT thread-safe so should be protected by fSafe.Lock/UnLock
function Delete(const aKey): PtrInt;
Delete a key/value association from its supplied aKey
- this would delete the entry, i.e. matching key and value pair
- returns the index of the deleted item, -1 if aKey was not found
- this method is thread-safe, since it will lock the instance
function DeleteAt(aIndex: PtrInt): boolean;
Delete a key/value association from its internal index
- this method is not thread-safe: you should use fSafe.Lock/Unlock e.g. then Find/FindValue to retrieve the index value
function DeleteDeprecated(tix64: Int64 = 0): integer;
Search and delete all deprecated items according to TimeoutSeconds
- returns how many items have been deleted
- you can call this method very often: it will ensure that the search process will take place at most once every second
- this method is thread-safe, but blocking during the process
function DeleteInArray(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Clear aArrayValue item of a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, then use TDynArray.FindAndDelete to delete any aArrayValue match in the associated dynamic array
- returns FALSE if Values is not a tkDynArray, or if aKey or aArrayValue were not found
- this method is thread-safe, since it will lock the instance
function Exists(const aKey): boolean;
Search for a primary key presence
- returns TRUE if aKey was found, FALSE if no match exists
- this method is thread-safe
function ExistsValue(const aValue; aCompare: TDynArraySortCompare = nil): boolean;
Search for a value presence
- returns TRUE if aValue was found, FALSE if no match exists
- this method is thread-safe, but will use O(n) slow browsing
function Find(const aKey; aUpdateTimeOut: boolean = false): PtrInt;
Search of a primary key within the internal hashed dictionary
- returns the index of the matching item, -1 if aKey was not found
- if you want to access the value, you should use fSafe.Lock/Unlock: consider using Exists or FindAndCopy thread-safe methods instead
- aUpdateTimeOut will update the associated timeout value of the entry
function FindAndCopy(const aKey; var aValue; aUpdateTimeOut: boolean = true): boolean;
Search of a stored value by its primary key, and return a local copy
- so this method is thread-safe
- returns TRUE if aKey was found, FALSE if no match exists
- will update the associated timeout value of the entry, unless aUpdateTimeOut is set to false
function FindAndDeleteDeprecated(const aKey; aSeconds: integer): boolean;
Search of a stored value, and delete it if its timeout was set too long ago
- returns true if aKey was found and deleted
- returns false if aKey was not found or the entry not deprecated
- this method is thread-safe
function FindAndExtract(const aKey; var aValue): boolean;
Search of a stored value by its primary key, then delete and return it
- returns TRUE if aKey was found, fill aValue with its content, and delete the entry in the internal storage
- so this method is thread-safe
- returns FALSE if no match exists
function FindAndGetElapsedSeconds(const aKey): integer;
Search of a stored value, and return seconds since its timeout was set
- returns -1 if aKey was not found
- this method is thread-safe
function FindInArray(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Search aArrayValue item in a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, then use TDynArray.Find to delete any aArrayValue match in the associated dynamic array
- returns FALSE if Values is not a tkDynArray, or if aKey or aArrayValue were not found
- this method is thread-safe, since it will lock the instance
function FindKeyFromValue(const aValue; out aKey; aUpdateTimeOut: boolean = true): boolean;
Search of a stored key by its associated key, and return a key local copy
- won't use any hashed index but RTTI TDynArray.IndexOf search over over fValues() so is much slower than FindAndCopy() for huge arrays
- will update the associated timeout value of the entry, unless aUpdateTimeOut is set to false
- this method is thread-safe
- returns TRUE if aValue was found, FALSE if no match exists
function FindValue(const aKey; aUpdateTimeOut: boolean = false; aIndex: PPtrInt = nil): pointer;
Search of a primary key within the internal hashed dictionary
- returns a pointer to the matching item, nil if aKey was not found
- if you want to access the value, you should use fSafe.Lock/Unlock: consider using Exists or FindAndCopy thread-safe methods instead
- aUpdateTimeOut will update the associated timeout value of the entry
function FindValueOrAdd(const aKey; var added: boolean; aIndex: PPtrInt = nil): pointer;
Search of a primary key within the internal hashed dictionary
- returns a pointer to the matching or already existing value item
- if you want to access the value, you should use fSafe.Lock/Unlock: consider using Exists or FindAndCopy thread-safe methods instead
- will update the associated timeout value of the entry, if applying
function ForEach(const OnEach: TOnSynDictionary; Opaque: pointer = nil; MayModify: boolean = true): integer; overload;
Apply a specified event over all items stored in this dictionnary
- would browse the list in the adding order
- returns the number of times OnEach has been called
- this method is thread-safe - if the callback modifies the data, set MayModify=true and call fSafe.Lock/UnLock when writing
function ForEach(const OnMatch: TOnSynDictionary; KeyCompare, ValueCompare: TDynArraySortCompare; const aKey, aValue; Opaque: pointer = nil; MayModify: boolean = true): integer; overload;
Apply a specified event over matching items stored in this dictionnary
- would browse the list in the adding order, comparing each key and/or value item with the supplied comparison functions and aKey/aValue content
- returns the number of times OnMatch has been called, i.e. how many times KeyCompare(aKey,Keys[#])=0 or ValueCompare(aValue,Values[#])=0
- this method is thread-safe - if the callback modifies the data, set MayModify=true and call fSafe.Lock/UnLock when writing
function LoadFromBinary(const binary: RawByteString): boolean;
Load the content from SynLZ-compressed raw binary data
- as previously saved by SaveToBinary method
function LoadFromJson(const Json: RawUtf8; CustomVariantOptions: PDocVariantOptions = nil): boolean; overload;
Unserialize the content from "key":value JSON object
- if the JSON input may not be correct (i.e. if not coming from SaveToJson), you may set EnsureNoKeyCollision=TRUE for a slow but safe keys validation
function LoadFromJson(Json: PUtf8Char; CustomVariantOptions: PDocVariantOptions = nil): boolean; overload;
Unserialize the content from "key":value JSON object
- note that input JSON buffer is not modified in place: no need to create a temporary copy if the buffer is about to be re-used
class function OnCanDeleteSynPersistentLock( const aKey, aValue; aIndex: PtrInt): boolean;
Can be assigned to OnCanDeleteDeprecated to check TSynPersistentLock(aValue).Safe.IsLocked before actual deletion
function SaveToBinary(NoCompression: boolean = false; Algo: TAlgoCompress = nil): RawByteString;
Save the content as SynLZ-compressed raw binary data
- warning: this format is tied to the values low-level RTTI, so if you change the value/key type definitions, LoadFromBinary() would fail
function SaveToJson(EnumSetsAsText: boolean = false): RawUtf8; overload;
Serialize the content as a "key":value JSON object
function SaveValuesToJson(EnumSetsAsText: boolean = false; ReFormat: TTextWriterJsonFormat = jsonCompact): RawUtf8;
Serialize the Values[] as a JSON array
function UpdateInArray(const aKey, aArrayValue; aCompare: TDynArraySortCompare = nil): boolean;
Replace aArrayValue item of a dynamic-array value associated via aKey
- expect the stored value to be a dynamic array itself
- would search for aKey as primary key, then use TDynArray.FindAndUpdate to delete any aArrayValue match in the associated dynamic array
- returns FALSE if Values is not a tkDynArray, or if aKey or aArrayValue were not found
- this method is thread-safe, since it will lock the instance
procedure CopyValues(out Dest; ObjArrayByRef: boolean = false);
Make a copy of the stored values
- this method is thread-safe, since it will lock the instance during copy
- resulting length(Dest) will match the exact values count
- T*ObjArray will be reallocated and copied by content (using a temporary JSON serialization), unless ObjArrayByRef is true and pointers are copied
procedure DeleteAll;
Delete all key/value stored in the current instance
procedure SaveToJson(W: TJsonWriter; EnumSetsAsText: boolean = false); overload;
Serialize the content as a "key":value JSON object
procedure SetTimeoutAtIndex(aIndex: PtrInt);
Touch the entry timeout field so that it won't be deprecated sooner
- this method is not thread-safe, and is expected to be executed e.g. from a ForEach() TOnSynDictionary callback
property Capacity: integer read GetCapacity write SetCapacity;
Defines how many items are currently stored in Keys/Values internal arrays
- if you set a maximum size of this store (even a rough size), Add() are likely to be up to twice faster than letting the table grow by chunks
property CompressAlgo: TAlgoCompress read fCompressAlgo write fCompressAlgo;
The compression algorithm used for binary serialization
property Keys: TDynArrayHashed read fKeys;
Direct access to the primary key identifiers
- if you want to access the keys, you should use fSafe.Lock/Unlock
property OnCanDeleteDeprecated: TOnSynDictionaryCanDelete read fOnCanDelete write fOnCanDelete;
Callback to by-pass DeleteDeprecated deletion by returning false
- can be assigned e.g. to OnCanDeleteSynPersistentLock if Value is a TSynPersistentLock instance, to avoid any potential access violation
property ThreadUse: TSynLockerUse read GetThreadUse write SetThreadUse;
Can tune TSynDictionary threading process depending on your use case
- will redirect to the internal Safe TSynLocker instance
- warning: to be set only before any process is done
- advice: any performance impact should always be monitored, not guessed
property TimeOut: TCardinalDynArray read fTimeOut;
Direct low-level access to the internal access tick (GetTickCount64 shr 10)
- may be nil if TimeOutSeconds=0
property TimeOutSeconds: cardinal read GetTimeOutSeconds write SetTimeOutSeconds;
Returns the aTimeOutSeconds parameter value, as specified to Create()
- warning: setting a new timeout will clear all previous content
property Values: TDynArray read fValues;
Direct access to the associated stored values
- if you want to access the values, you should use fSafe.Lock/Unlock
TJsonSaveContext = object(TObject)
Internal stack-allocated structure for nested JSON serialization
- defined here for low-level use within TRttiJsonSave functions
Info: TRttiCustom;
The RTTI information of the current serialized type
Options: TTextWriterWriteObjectOptions;
Serialization options as specified for this process
- as used by AddShort/Add64/AddDateTime methods
Prop: PRttiCustomProp;
The RTTI information of the current serialized property
- is likely to be nil outside of properties serialization
W: TJsonWriter;
The associated stream writer for the JSON output
procedure Add64(Value: PInt64; UnSigned: boolean);
Some basic function to append an Int64 JSON value according to Options
procedure AddDateTime(Value: PDateTime; WithMS: boolean);
Some basic function to append a TDateTime JSON value according to Options
procedure AddShort(PS: PShortString);
Some basic function to append a shorstring JSON value according to Options
procedure AddShortBoolean(PS: PShortString; Value: boolean);
Some basic function to append a "name":boolean JSON pair value
procedure Init(WR: TJsonWriter; WriteOptions: TTextWriterWriteObjectOptions; Rtti: TRttiCustom);
Initialize this low-level JSON serialization context
TNameValuePUtf8Char = record
Store one name/value pair of raw UTF-8 content, from a JSON buffer
- used e.g. by JsonDecode() overloaded function or UrlEncodeJsonObject() to returns names/values
Name: TValuePUtf8Char;
Pointer and length to the actual UTF-8 name text
Value: TValuePUtf8Char;
Pointer and length to the actual UTF-8 value text
TJsonParserContext = object(TGetJsonField)
Efficient execution context of the JSON parser
- defined here for low-level use of TRttiJsonLoad functions
- inherit from TGetJsonField to include ParseNext/ParseNextAny unserialized Value/ValueLen and flags, and Json as current position in the JSON input
CustomVariant: PDocVariantOptions;
How TDocVariant should be created
DVO: TDocVariantOptions;
TDocVariant initialization options
Info: TRttiCustom;
Contains the current value RTTI
Interning: TRawUtf8Interning;
Optional RawUtf8 values interning
ObjectListItem: TRttiCustom;
Force the item class when reading a TObjectList without "ClassName":...
Options: TJsonParserOptions;
Customize parsing
Prop: PRttiCustomProp;
Contains the current property value RTTI
Valid: boolean;
True if the last parsing succeeded
function ParseArray: boolean;
Parse initial '[' token from JSON buffer
- once all the nested values have been read, call ParseEndOfObject
function ParseInteger: Int64;
Retrieve the next JSON value as integer
function ParseNewObject: TObject;
Parse a JSON object from the buffer into a
- if ObjectListItem was not defined, expect the JSON input to start as '{"ClassName":"TMyClass",...}'
function ParseNext: boolean;
Call inherited GetJsonField() to retrieve the next JSON value
- on success, return true and set Value/ValueLen and WasString fields
function ParseNextAny: boolean;
Call inherited GetJsonFieldOrObjectOrArray() to retrieve the next JSON value
- on success, return true and set Value/ValueLen and WasString fields
function ParseNull: boolean;
Parse a 'null' value from JSON buffer
function ParseObject(const Names: array of RawUtf8; Values: PValuePUtf8CharArray; HandleValuesAsObjectOrArray: boolean = false): boolean; overload;
Wrapper around JsonDecode() to easily get JSON object values
function ParseObject: boolean; overload;
Parse initial '{' token from JSON buffer
- once all the nested values have been read, call ParseEndOfObject
function ParseString: string;
Retrieve the next JSON value as RTL string text
function ParseUtf8: RawUtf8;
Retrieve the next JSON value as UTF-8 text
procedure InitParser(P: PUtf8Char; Rtti: TRttiCustom; O: TJsonParserOptions; CV: PDocVariantOptions; ObjectListItemClass: TClass; RawUtf8Interning: TRawUtf8Interning);
Initialize this unserialization context
procedure ParseEndOfObject;
Set the EndOfObject field of a JSON buffer, just like GetJsonField() does
- to be called whan a JSON object or JSON array has been manually parsed
procedure ParsePropComplex(Data: pointer);
Parse a property value, properly calling any setter
TRttiJson = class(TRttiCustom)
JSON-aware TRttiCustom class - used for global RttiCustom: TRttiCustomList
class function Find(Info: PRttiInfo): TRttiJson;
Efficient search of TRttiJson from a given RTTI TypeInfo()
- to be used instead of Rtti.Find() to return directly the TRttiJson instance
function ParseNewInstance(var Context: TJsonParserContext): TObject;
Create and parse a new TObject instance of this rkClass
class function RegisterCustomSerializer(Info: PRttiInfo; const Reader: TOnRttiJsonRead; const Writer: TOnRttiJsonWrite): TRttiJson;
Register a custom callback for JSON serialization of a given TypeInfo()
- for a dynamic array, will customize the item serialization callbacks
- replace deprecated TTextWriter.RegisterCustomJSONSerializer() method
class function RegisterCustomSerializerClass(ObjectClass: TClass; const Reader: TOnClassJsonRead; const Writer: TOnClassJsonWrite): TRttiJson;
Register a custom callback for JSON serialization of a given class
- replace deprecated TTextWriter.RegisterCustomJSONSerializer() method
class function RegisterFromText(DynArrayOrRecord: PRttiInfo; const RttiDefinition: RawUtf8; IncludeReadOptions: TJsonParserOptions; IncludeWriteOptions: TTextWriterWriteObjectOptions): TRttiJson;
Register TypeInfo() custom JSON serialization for a given dynamic array or record
- to be used instead of homonomous Rtti.RegisterFromText() to supply an additional set of serialization/unserialization JSON options
class function UnRegisterCustomSerializer(Info: PRttiInfo): TRttiJson;
Unregister any custom callback for JSON serialization of a given TypeInfo()
- will also work after RegisterFromText()
class function UnRegisterCustomSerializerClass(ObjectClass: TClass): TRttiJson;
Unregister any custom callback for JSON serialization of a given class
function ValueByPath(var Data: pointer; Path: PUtf8Char; var Temp: TVarData; PathDelim: AnsiChar = '.'): TRttiCustom; override;
Lookup a value by a path name e.g. 'one.two.three' nested values
- for a record/class, will search for a property name
- for a TDocVariant/TBsonVariant, calls TSynInvokeableVariantType.IntGet
- for an enumeration or set, will return true/false about the enum name
- for a string, Data^ will be compared to the name
function ValueCompare(Data, Other: pointer; CaseInsensitive: boolean): integer; override;
Compare two stored values of this type
function ValueIterate(Data: pointer; Index: PtrUInt; out ResultRtti: TRttiCustom): pointer; override;
Iterate over one sub-item of a given value
- returns nil if the value is not iterable or Index is out of range
- returns a pointer to the value, rkClass/rkLString kinds being already resolved (as the TList/TSynList/TRawUtf8List items are returned), so you can directly trans-type the result to TObject() or RawUtf8()
- ResultRtti holds the type of the resolved result pointer
- note that TStrings values are not supported, because they require a temporary string variable for their getter method
function ValueIterateCount(Data: pointer): integer; override;
How many iterations could be done one a given value
- returns -1 if the value is not iterable, or length(DynArray) or TRawUtf8List.Count or TList.Count or TSynList.Count
- note that TStrings values are not supported, because they require a temporary string variable for their getter
function ValueToVariant(Data: pointer; out Dest: TVarData; Options: pointer = nil): PtrInt; override;
Fill a variant with a stored value of this type
- complex values can be returned as TDocVariant after JSON conversion, using e.g. @JSON_[mFast] as optional Options parameter
procedure RawLoadJson(Data: pointer; var Ctxt: TJsonParserContext);
Simple wrapper around TRttiJsonLoad(fJsonLoad)
procedure RawSaveJson(Data: pointer; const Ctxt: TJsonSaveContext);
Simple wrapper around TRttiJsonSave(fJsonSave)
procedure ValueLoadJson(Data: pointer; var Json: PUtf8Char; EndOfObject: PUtf8Char; ParserOptions: TJsonParserOptions; CustomVariantOptions: PDocVariantOptions; ObjectListItemClass: TClass; Interning: TRawUtf8Interning);
Unserialize some JSON input into Data^
- as used by LoadJson() and similar high-level functions
procedure ValueWriteText(Data: pointer; W: TTextWriter; HtmlEscape: boolean); override;
Serialize a value into (HTML) text
- warning: supplied W instance should be a TJsonWriter
property IncludeReadOptions: TJsonParserOptions read fIncludeReadOptions write fIncludeReadOptions;
Define an additional set of unserialization JSON options
- is included for this type to the supplied TJsonParserOptions
property IncludeWriteOptions: TTextWriterWriteObjectOptions read fIncludeWriteOptions write fIncludeWriteOptions;
Define an additional set of serialization JSON options
- is included for this type to the supplied TTextWriterWriteObjectOptions
TPersistentAutoCreateFields = class(TPersistentWithCustomCreate)
Abstract TPersistent class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed
- TSynAutoCreateFields is to be preferred in most cases, thanks to its lower overhead
- note that non published (e.g. public) properties won't be instantiated, serialized, nor released - but may contain weak references to other classes
- please take care that you will not create any endless recursion: you should ensure that at one level, nested published properties won't have any class instance refering to its owner (there is no weak reference - remember!)
- since the destructor will release all nested properties, you should never store a reference to any of those nested instances if this owner may be freed before
constructor Create; override;
This overriden constructor will instantiate all its nested class or T*ObjArray published properties
destructor Destroy; override;
Finalize the instance, and its class or T*ObjArray published properties
TSynAutoCreateFields = class(TSynPersistent)
Our own empowered TPersistentAutoCreateFields-like parent class
- this class is a perfect parent to store any data by value, e.g. DDD Value Objects, Entities or Aggregates
- is defined as an abstract class able with a virtual constructor, RTTI for published properties, and automatic memory management of all nested class published properties: any class defined as a published property will be owned by this instance - i.e. with strong reference
- will also release any T*ObjArray dynamic array storage of persistents, previously registered via Rtti.RegisterObjArray() for Delphi 7-2009
- nested published classes (or T*ObjArray) don't need to inherit from TSynAutoCreateFields: they may be from any TPersistent/TSynPersistent type
- note that non published (e.g. public) properties won't be instantiated, serialized, nor released - but may contain weak references to other classes
- please take care that you will not create any endless recursion: you should ensure that at one level, nested published properties won't have any class instance refering to its owner (there is no weak reference - remember!)
- since the destructor will release all nested properties, you should never store a reference to any of those nested instances if this owner may be freed before
- TPersistent/TPersistentAutoCreateFields have an unexpected speed overhead due a giant lock introduced to manage property name fixup resolution (which we won't use outside the UI) - this class is definitively faster
constructor Create; override;
This overriden constructor will instantiate all its nested class or T*ObjArray published properties
destructor Destroy; override;
Finalize the instance, and its class or T*ObjArray published properties
TSynAutoCreateFieldsLocked = class(TSynPersistentLock)
Adding locking methods to a TSynAutoCreateFields with virtual constructor
constructor Create; override;
Initialize the object instance, its associated lock, and its nested class or T*ObjArray published properties
destructor Destroy; override;
Release the instance (including the locking resource) and nested classes
TInterfacedObjectAutoCreateFields = class(TInterfacedObjectWithCustomCreate)
Abstract TInterfacedObject class, which will instantiate all its nested class published properties, then release them when freed
- will handle automatic memory management of all nested class and T*ObjArray published properties: any class or T*ObjArray defined as a published property will be owned by this instance - i.e. with strong reference
- non published properties (e.g. public) won't be instantiated, so may store weak class references
- could be used for gathering of TCollectionItem properties, e.g. for Domain objects in DDD, especially for list of value objects, with some additional methods defined by an Interface
- since the destructor will release all nested properties, you should never store a reference to any of those nested instances if this owner may be freed before
constructor Create; override;
This overriden constructor will instantiate all its nested class or T*ObjArray published properties
destructor Destroy; override;
Finalize the instance, and release its published properties
ISerializable = interface(IInterface)
Abstract interface parent with common methods for JSON serialization
- to implement this, you can inherit from TInterfacedSerializable or TInterfacedSerializableAutoCreateFields
function GetJson: RawUtf8;
Methods used as getter/setter for the Json property
function ToJson(format: TTextWriterJsonFormat; options: TTextWriterWriteObjectOptions = []): RawUtf8; overload;
Serialize this instance into a JSON array/object specific format
function ToString(format: TTextWriterJsonFormat = jsonCompact; options: TTextWriterWriteObjectOptions = []): string;
Convert this instance into JSON array/object as RTL string
procedure FromJson(var Context: TJsonParserContext);
Raw unserialization of a JSON content into this instance
procedure ToJson(W: TJsonWriter; options: TTextWriterWriteObjectOptions); overload;
Raw serialization of this instance into a JSON writer
property Json: RawUtf8 read GetJson write SetJson;
Unserialize/serialize this IDocList/IDocDict from/into a JSON array/object
- use ToString if you want the result as RTL string
TInterfacedSerializable = class(TInterfacedObject)
Abstract class parent with ISerializable methods for JSON serialization
- you need to override Create, ToJson and FromJson abstract methods
constructor Create(options: PDocVariantOptions); reintroduce; virtual; abstract;
Factory of one class implementing a ISerializable interface
- this abstract method must be overriden
class function Guid: PGuid;
Return the associated ISerializer sub-interface TGuid
- as registered by RegisterToRtti() class method
class function RegisterToRtti(InterfaceInfo: PRttiInfo): TRttiJson;
Register this class to implement a given ISerializer sub-interface
function ToJson(format: TTextWriterJsonFormat; options: TTextWriterWriteObjectOptions): RawUtf8; overload; virtual;
Serialize this instance into a JSON array/object specific format
function ToString(format: TTextWriterJsonFormat; options: TTextWriterWriteObjectOptions): string; reintroduce; virtual;
Convert this instance into JSON array/object as RTL string
procedure FromJson(var context: TJsonParserContext); virtual; abstract;
Raw unserialization of a JSON content into this instance
- this abstract method must be overriden
class procedure NewInterface(out Obj);
Create a new instance as the associated ISerializer sub-interface
- as registered by RegisterToRtti() class method
procedure ToJson(W: TJsonWriter; options: TTextWriterWriteObjectOptions); overload; virtual; abstract;
Raw serialization of this instance into a JSON writer
- this abstract method must be overriden
property Json: RawUtf8 read GetJson write SetJson;
Unserialize/serialize this instance from/into a JSON array/object
- use ToString if you want the result as RTL string
TInterfacedSerializableAutoCreateFields = class(TInterfacedSerializable)
Abstract ISerializable class parent with auto-create published fields
- you should inherit this class, associated with an interface inheriting from ISerializable (and propably with a method returning self to access the properties), then call once the RegisterToRtti() class function
- could be used e.g. to implement a DDD/KDD Aggregate object with both ref-counted data and methods, ready to be serialized over SOA
constructor Create(options: PDocVariantOptions = nil); override;
Instantiate all nested class or T*ObjArray published properties
destructor Destroy; override;
Finalize the instance, and release its published properties
procedure FromJson(var context: TJsonParserContext); override;
Raw JSON unserialization into the published properties of this instance
procedure ToJson(W: TJsonWriter; options: TTextWriterWriteObjectOptions); override;
Raw JSON serialization of the published properties of this instance
property RttiJson: TRttiJson read fRttiJson;
Low-level access to the RTTI information associated with this class
TCollectionItemAutoCreateFields = class(TCollectionItem)
Abstract TCollectionItem class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed
- could be used for gathering of TCollectionItem properties, e.g. for Domain objects in DDD, especially for list of value objects
- consider using T*ObjArray dynamic array published properties in your value types instead of TCollection storage: T*ObjArray have a lower overhead and are easier to work with, once Rtti.RegisterObjArray is called on Delphi 7-2009 to register the T*ObjArray type (not needed on FPC and Delphi 2010+)
- note that non published (e.g. public) properties won't be instantiated, serialized, nor released - but may contain weak references to other classes
- please take care that you will not create any endless recursion: you should ensure that at one level, nested published properties won't have any class instance refering to its owner (there is no weak reference - remember!)
- since the destructor will release all nested properties, you should never store a reference to any of those nested instances if this owner may be freed before
constructor Create(Collection: TCollection); override;
This overriden constructor will instantiate all its nested class or T*ObjArray published properties
destructor Destroy; override;
Finalize the instance, and release its published properties
TSynJsonFileSettings = class(TSynAutoCreateFields)
Abstract parent class able to store settings as JSON file
- would fallback and try to read as INI file if no valid JSON is found
function FolderName: TFileName;
Just a wrapper around ExtractFilePath(FileName);
function LoadFromFile(const aFileName: TFileName; const aSectionName: RawUtf8 = 'Main'): boolean; virtual;
Read existing settings from a JSON or INI file file
function LoadFromJson(const aJson: RawUtf8; const aSectionName: RawUtf8 = 'Main'): boolean;
Read existing settings from a JSON content
- if the input is no JSON object, then a .INI structure is tried
function SaveIfNeeded: boolean; virtual;
Persist the settings as a JSON file, named from LoadFromFile() parameter
- will use the INI format if it was used at loading, or fsoWriteIni is set
- return TRUE if file has been modified, FALSE if was not needed or failed
property FileName: TFileName read fFileName write fFileName;
Optional persistence file name, as set by LoadFromFile()
property InitialFileHash: cardinal read fInitialFileHash write fInitialFileHash;
Can be used to compare two instances original file content
- will use DefaultHasher, so hash could change after process restart
property SettingsOptions: TSynJsonFileSettingsOptions read fSettingsOptions write fSettingsOptions;
Allow to customize the storing process
PInterfacedSerializable = ^TInterfacedSerializable;
Points to a TInterfacedSerializable class instance
PJsonCharSet = ^TJsonCharSet;
Points to a lookup table used for branch-less JSON parsing
PJsonTokens = ^TJsonTokens;
Points to a lookup table used for branch-less first char JSON parsing
PSynNameValue = ^TSynNameValue;
A reference pointer to a Name/Value RawUtf8 pairs storage
TInterfacedObjectAutoCreateFieldsClass = class of TInterfacedObjectAutoCreateFields;
Meta-class definition of TInterfacedObjectAutoCreateFields
TInterfacedSerializableClass = class of TInterfacedSerializable;
Meta-class of the TInterfacedSerializable type
TJsonChar = set of ( jcJsonIdentifierFirstChar, jcJsonIdentifier, jcEndOfJsonFieldOr0, jcEndOfJsonFieldNotName, jcEndOfJsonValueField, jcJsonStringMarker, jcDigitFirstChar, jcDigitFloatChar);
Kind of character used from JSON_CHARS[] for efficient JSON parsing
- using such a set compiles into TEST [MEM], IMM so is more efficient than a regular set of AnsiChar which generates much slower BT [MEM], IMM
- the same 256-byte memory will also be reused from L1 CPU cache during the parsing of complex JSON input
- TTestCoreProcess.JSONBenchmark shows around 900MB/s on my i5 notebook
TJsonCharSet = array[AnsiChar] of TJsonChar;
Defines a lookup table used for branch-less JSON parsing
TJsonParserOption = ( jpoIgnoreUnknownProperty, jpoIgnoreStringType, jpoIgnoreUnknownEnum, jpoHandleCustomVariants, jpoHandleCustomVariantsWithinString, jpoSetterExpectsToFreeTempInstance, jpoSetterNoCreate, jpoAllowInt64Hex, jpoAllowDouble, jpoObjectListClassNameGlobalFindClass, jpoNullDontReleaseObjectInstance, jpoClearValues );
Available options for JSON parsing process
- by default, parsing will fail if a JSON field name is not part of the object published properties, unless jpoIgnoreUnknownProperty is defined - this option will also ignore read-only properties (i.e. with only a getter)
- by default, function will check that the supplied JSON value will be a JSON string when the property is a string, unless jpoIgnoreStringType is defined and JSON numbers are accepted and stored as text
- by default any unexpected value for enumerations will be marked as invalid, unless jpoIgnoreUnknownEnum is defined, so that in such case the ordinal 0 value is left, and loading continues
- by default, only simple kind of variant types (string/numbers) are handled: set jpoHandleCustomVariants if you want to handle any custom - in this case , it will handle direct JSON [array] of {object}: but if you also define jpoHandleCustomVariantsWithinString, it will also try to un-escape a JSON string first, i.e. handle "[array]" or "{object}" content (may be used e.g. when JSON has been retrieved from a database TEXT column)
- by default, a temporary instance will be created if a published field has a setter, and the instance is expected to be released later by the owner class: set jpoSetterExpectsToFreeTempInstance to let JsonParser (and TPropInfo.ClassFromJson) release it when the setter returns, and jpoSetterNoCreate to avoid the published field instance creation
- set jpoAllowInt64Hex to let Int64/QWord fields accept hexadecimal string (as generated e.g. via the woInt64AsHex option)
- by default, double values won't be stored as variant values, unless jpoAllowDouble is set - see also dvoAllowDoubleValue in TDocVariantOptions
- jpoObjectListClassNameGlobalFindClass would also search for "ClassName": TObjectList serialized field with the global Classes.FindClass() function
- null will release any class instance, unless jpoNullDontReleaseObjectInstance is set which will leave the instance untouched
- values will be left untouched before parsing, unless jpoClearValues is defined, to void existing record fields or class published properties
TJsonParserOptions = set of TJsonParserOption;
Set of options for JsonParser() parsing process
TJsonToken = ( jtNone, jtDoubleQuote, jtFirstDigit, jtNullFirstChar, jtTrueFirstChar, jtFalseFirstChar, jtObjectStart, jtArrayStart, jtObjectStop, jtArrayStop, jtAssign, jtComma, jtSingleQuote, jtEqual, jtIdentifierFirstChar, jtSlash, jtEndOfBuffer );
Kind of first character used from JSON_TOKENS[] for efficient JSON parsing
TJsonTokens = array[AnsiChar] of TJsonToken;
Defines a lookup table used for branch-less first char JSON parsing
TJsonToObjectOption = TJsonParserOption;
Backward compatibility types redirections
TNameValuePUtf8CharDynArray = array of TNameValuePUtf8Char;
Used e.g. by JsonDecode() overloaded function to returns name/value pairs
TOnClassJsonRead = procedure(var Context: TJsonParserContext; Instance: TObject) of object;
The callback signature used by TRttiJson for unserializing JSON classes
- set Context.Valid=true if Context.JSON has been parsed into Instance
- is in fact a convenient alias to the TOnRttiJsonRead callback
TOnClassJsonWrite = procedure(W: TJsonWriter; Instance: TObject; Options: TTextWriterWriteObjectOptions) of object;
The callback signature used by TRttiJson for serializing JSON classes
- Instance should be written into W, with the supplied Options
- is in fact a convenient alias to the TOnRttiJsonWrite callback
TOnRttiJsonRead = procedure(var Context: TJsonParserContext; Data: pointer) of object;
The callback signature used by TRttiJson for unserializing JSON data
- set Context.Valid=true if Context.JSON has been parsed into Data^
TOnRttiJsonWrite = procedure(W: TJsonWriter; Data: pointer; Options: TTextWriterWriteObjectOptions) of object;
The callback signature used by TRttiJson for serializing JSON data
- Data^ should be written into W, with the supplied Options
TOnSynDictionary = function(const aKey; var aValue; aIndex, aCount: integer; aOpaque: pointer): boolean of object;
Event called by TSynDictionary.ForEach methods to iterate over stored items
- if the implementation method returns TRUE, will continue the loop
- if the implementation method returns FALSE, will stop values browsing
- aOpaque is a custom value specified at ForEach() method call
TOnSynDictionaryCanDelete = function(const aKey, aValue; aIndex: integer): boolean of object;
Event called by TSynDictionary.DeleteDeprecated
- called just before deletion: return false to by-pass this item
TOnSynNameValueConvertRawUtf8 = function( const text: RawUtf8): RawUtf8 of object;
Event handler used to convert on the fly some UTF-8 text content
TOnSynNameValueNotify = procedure( const Item: TSynNameValueItem; Index: PtrInt) of object;
Callback event used by TSynNameValue
TRttiJsonLoad = procedure(Data: pointer; var Ctxt: TJsonParserContext);
Internal function handler for JSON reading of any TRttiParserType value
TRttiJsonSave = procedure(Data: pointer; const Ctxt: TJsonSaveContext);
Internal function handler for JSON persistence of any TRttiParserType value
- i.e. the kind of functions called via PT_JSONSAVE[] lookup table
TSynAutoCreateFieldsClass = class of TSynAutoCreateFields;
Meta-class definition of TSynAutoCreateFields
TSynAutoCreateFieldsLockedClass = class of TSynAutoCreateFieldsLocked;
Meta-class definition of TSynAutoCreateFieldsLocked
TSynDictionaryInArray = ( iaFind, iaFindAndDelete, iaFindAndUpdate, iaFindAndAddIfNotExisting, iaAdd, iaAddForced );
Internal flag, used only by TSynDictionary.InArray protected method
TSynJsonFileSettingsClass = class of TSynJsonFileSettings;
Meta-class definition of TSynJsonFileSettings
TSynJsonFileSettingsOption = ( fsoDisableSaveIfNeeded, fsoReadIni, fsoWriteIni );
Customize TSynJsonFileSettings process
- fsoDisableSaveIfNeeded will disable SaveIfNeeded method process
- fsoReadIni will disable JSON loading, and expect INI file format
- fsoWriteIni will force SaveIfNeeded to use the INI layout
TSynNameValueItemDynArray = array of TSynNameValueItem;
Name/Value pairs storage, as used by TSynNameValue class
DIC_KEY = 1;
Keys.Count integer
DIC_KEYCOUNT = 0;
TSynDictionary.fSafe.Padding[DIC_*] place holders - defined here for inlining
DIC_TIMECOUNT = 4;
Values.Value pointer
DIC_TIMESEC = 5;
Timeouts.Count integer
DIC_TIMETIX = 6;
Timeouts Seconds integer
DIC_VALUE = 3;
Values.Count integer
DIC_VALUECOUNT = 2;
Key.Value pointer
JSON_ESCAPE_ENDINGZERO = 1;
JSON_ESCAPE[] lookup value: indicates #0 (end of string)
JSON_ESCAPE_NONE = 0;
JSON_ESCAPE[] lookup value: indicates no escape needed
JSON_ESCAPE_UNICODEHEX = 2;
JSON_ESCAPE[] lookup value: should be escaped as \u00xx
JSON_UNESCAPE_UNEXPECTED = #0;
JSON_UNESCAPE[] lookup value: indicates #0 or unexpected control char
JSON_UNESCAPE_UTF16 = #1;
JSON_UNESCAPE[] lookup value: indicates '\u0123' UTF-16 pattern
ROWCOUNT_PATTERN: PUtf8Char = ',"rowCount":';
PatternLen = 14 chars
VALUES_PATTERN: PUtf8Char = ',"values":[';
PatternLen = 12 chars
XMLUTF8_HEADER = '<?xml version="1.0" encoding="UTF-8"?>'#13#10;
Standard header for an UTF-8 encoded XML file
XMLUTF8_NAMESPACE = '<contents xmlns="http://www.w3.org/2001/XMLSchema-instance">';
Standard namespace for a generic XML File
| Functions or procedures | Description | |
|---|---|---|
| AutoCreateFields | Should be called by T*AutoCreateFields constructors | |
| AutoDestroyFields | Should be called by T*AutoCreateFields destructors | |
| DoRegisterAutoCreateFields | Internal function called by AutoCreateFields() when inlined | |
| DynArrayBlobSaveJson | Serialize a dynamic array content, supplied as raw binary buffer, as JSON | |
| DynArrayLoadJson | Fill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson with or without twoNonExpandedArrays layout | |
| DynArrayLoadJson | Fill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson, which won't be modified | |
| DynArraySaveJson | Serialize a dynamic array content as JSON | |
| Expect | PatternLen = 11 chars quickly check if an UTF-8 buffer start with the supplied Pattern | |
| FormatJson | Fast Format() function replacement, handling % but also ? parameters as JSON | |
| FormatParams | Fast Format() function replacement, handling % and ? parameters | |
| FormatSql | Fast Format() function replacement, handling % but also ? inlined parameters | |
| FormatUtf8 | Rather call FormatSql() and FormatJson() functions | |
| GetFieldCountExpanded | Low-level parsing of the first expanded JSON object to guess fields count | |
| GetFirstJsonToken | Returns the JSON type of a supplied #0 ended buffer | |
| GetJsonField | Decode a JSON field value in-place from an UTF-8 encoded text buffer | |
| GetJsonFieldOrObjectOrArray | Decode a JSON content from an UTF-8 encoded buffer | |
| GetJsonItemAsRawJson | Retrieve the next JSON item as a RawJson undecoded variable | |
| GetJsonItemAsRawUtf8 | Retrieve the next JSON item as a RawUtf8 decoded buffer | |
| GetJsonObjectOrArray | Decode a JSON object or array from an UTF-8 encoded buffer | |
| GetJsonPropName | Decode a JSON field name in an UTF-8 encoded buffer | |
| GetJsonPropNameShort | Decode a JSON field name in an UTF-8 encoded ShortString variable | |
| GetNextJsonToken | Validate the supplied #0 ended buffer and returns its JSON type | |
| GetSetNameValue | Helper to retrieve the bit mapped integer value of a set from its JSON text | |
| GetSetNameValue | Helper to retrieve the bit mapped integer value of a set from its JSON text | |
| GetValueObject | Get any (potentially nested) object property by path | |
| GotoEndJsonItem | Reach position just after the current JSON item in the supplied UTF-8 buffer | |
| GotoEndJsonItemStrict | Reach position just after the current JSON item in the supplied UTF-8 buffer | |
| GotoEndJsonItemString | Reach position just after the current JSON string in the supplied UTF-8 buffer | |
| GotoEndOfJsonString | Get the next character after a quoted buffer | |
| GotoFieldCountExpanded | Low-level prepare GetFieldCountExpanded() parsing returning '{' or ']' | |
| GotoNextJsonItem | Reach the position of the next JSON item(s) in the supplied UTF-8 buffer | |
| GotoNextJsonItem | Reach the position of the next JSON item in the supplied UTF-8 buffer | |
| IgnoreComma | Simple method to go after the next ',' character | |
| IsNotExpandedBuffer | Parse JSON content in not-expanded format | |
| IsString | Test if the supplied buffer is a "string" value or a numerical value (floating point or integer), according to the characters within | |
| IsStringJson | Test if the supplied buffer is a "string" value or a numerical value (floating or integer), according to the JSON encoding schema | |
| IsValidJson | Test if the supplied text seems to be a correct (extended) JSON value | |
| IsValidJson | Test if the supplied text buffer seems to be a correct (extended) JSON value | |
| IsValidJsonBuffer | Test if the supplied #0 ended buffer is a correct (extended) JSON value | |
| JsonArrayCount | Compute the number of elements of a JSON array | |
| JsonArrayDecode | Retrieve the positions of all elements of a JSON array | |
| JsonArrayItem | Go to the #nth item of a JSON array | |
| JsonBufferReformat | Formats and indents a JSON array or document to the specified layout | |
| JsonBufferReformatToFile | Formats and indents a JSON array or document as a file | |
| JsonBufferToXML | Convert a JSON array or document into a simple XML content | |
| JsonDecode | Decode the supplied UTF-8 JSON object for the one supplied field name | |
| JsonDecode | Decode the supplied UTF-8 JSON content for the supplied names | |
| JsonDecode | Decode the supplied UTF-8 JSON content for the supplied names | |
| JsonDecode | Decode the supplied UTF-8 JSON object for the one supplied field name | |
| JsonDecode | Decode the supplied UTF-8 JSON object for the supplied field names | |
| JsonDecode | Decode the supplied UTF-8 JSON object for the supplied field names | |
| JsonDecode | Decode the supplied UTF-8 JSON object into an array of name/value pairs | |
| JsonEncode | Encode the supplied data as an UTF-8 valid JSON object content | |
| JsonEncode | Encode the supplied (extended) JSON content, with parameters, as an UTF-8 valid JSON object content | |
| JsonEncodeArrayDouble | Encode the supplied floating-point array data as a valid JSON array | |
| JsonEncodeArrayInteger | Encode the supplied integer array data as a valid JSON array | |
| JsonEncodeArrayOfConst | Encode the supplied array data as a valid JSON array content | |
| JsonEncodeArrayOfConst | Encode the supplied array data as a valid JSON array content | |
| JsonEncodeArrayUtf8 | Encode the supplied RawUtf8 array data as an UTF-8 valid JSON array content | |
| JsonEncodeNameSQLValue | Encode as JSON {"name":value} object, from a potential SQL quoted value | |
| JsonFileToObject | Fill the object properties from a JSON file content | |
| JsonObjectAsJsonArrays | Convert one JSON object into two JSON arrays of keys and values | |
| JsonObjectByPath | Go to a property of a JSON object, by its full path, e.g. 'parent.child' | |
| JsonObjectItem | Go to a buffer-named property of a JSON object | |
| JsonObjectItem | Go to a named property of a JSON object | |
| JsonObjectPropCount | Compute the number of fields in a JSON object | |
| JsonObjectsByPath | Return all matching properties of a JSON object | |
| JsonPropNameValid | Returns TRUE if the given text buffer contains simple characters as recognized by JSON extended syntax | |
| JsonReformat | Formats and indents a JSON array or document to the specified layout | |
| JsonReformatToFile | Formats and indents a JSON array or document as a file | |
| JsonRetrieveObjectRttiCustom | Retrieve a class Rtti, as saved by ObjectToJson(...,[...,woStoreClassName,...]); | |
| JsonRetrieveStringField | Retrieve a pointer to JSON string field content, without unescaping it | |
| JsonSettingsToObject | Parse the supplied JSON with some tolerance about Settings format | |
| JsonToNewObject | Create a new object instance, as saved by ObjectToJson(...,[...,woStoreClassName,...]); | |
| JsonToObject | Read an object properties, as saved by ObjectToJson function | |
| JsonToXML | Convert a JSON array or document into a simple XML content | |
| JsonUnicodeEscape | {$ifdef HASINLINE}inline;{$endif} ensure all UTF-8 Unicode glyphs are escaped as \u#### UTF-16 JSON | |
| JsonUnicodeEscapeToUtf8 | UTF-8 decode one or two \u#### JSON escaped codepoints into Dest | |
| JsonUnicodeUnEscape | Ensure all \u#### UTF-16 JSON are decoded into plain UTF-8 content | |
| LoadJson | Unserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson | |
| LoadJsonInPlace | Unserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson | |
| NeedsJsonEscape | Returns TRUE if the given text buffers would be escaped when written as JSON | |
| NeedsJsonEscape | Returns TRUE if the given text buffers would be escaped when written as JSON | |
| NeedsJsonEscape | Returns TRUE if the given text buffers would be escaped when written as JSON | |
| NotExpandedBufferRowCountPos | Efficient retrieval of the number of rows in non-expanded layout | |
| ObjArrayToJson | Wrapper to serialize a T*ObjArray dynamic array as JSON | |
| ObjectLoadJson | Read an object properties, as saved by ObjectToJson function | |
| ObjectsToJson | Will serialize set of TObject into its UTF-8 JSON representation | |
| ObjectToJsonFile | Persist a class instance into a JSON file | |
| ParseEndOfObject | Search the EndOfObject of a JSON buffer, just like TGetJsonField does | |
| PropertyFromJson | Read an TObject published property, as saved by ObjectToJson() function | |
| QuotedStrJson | Convert UTF-8 content into a JSON string | |
| QuotedStrJson | Convert UTF-8 buffer into a JSON string | |
| QuotedStrJson | Convert UTF-8 content into a JSON string | |
| RecordLoadJson | Fill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson | |
| RecordLoadJson | Fill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson | |
| RecordSaveJson | Save record into its JSON serialization as saved by TJsonWriter.AddRecordJson | |
| RemoveCommentsFromJson | Remove comments from a text buffer before passing it to JSON parser | |
| RemoveCommentsFromJson | Remove comments and trailing commas from a text buffer before passing it to a JSON parser | |
| SaveJson | Serialize most kind of content as JSON, using its RTTI | |
| SaveJson | Serialize most kind of content as JSON, using its RTTI | |
| SaveJson | Serialize most kind of content as JSON, using its RTTI and a type name | |
| SaveJson | Serialize most kind of content as JSON, using its RTTI | |
| UrlDecodeObject | Decode a specified parameter compatible with URI encoding into its original object contents | |
| UrlEncodeJsonObject | Encode a JSON object UTF-8 buffer into URI parameters | |
| UrlEncodeJsonObject | Encode a JSON object UTF-8 buffer into URI parameters | |
| Utf16ToJsonUnicodeEscape | Encode one \u#### JSON escaped UTF-16 codepoint into Dest |
function AutoCreateFields(ObjectInstance: TObject): TRttiJson;
Should be called by T*AutoCreateFields constructors
- will also register this class type, if needed, so RegisterClass() is redundant to this method
procedure AutoDestroyFields(ObjectInstance: TObject; Info: TRttiJson = nil);
Should be called by T*AutoCreateFields destructors
- constructor should have called AutoCreateFields()
function DoRegisterAutoCreateFields(ObjectInstance: TObject): TRttiJson;
Internal function called by AutoCreateFields() when inlined
- do not call this internal function, but always AutoCreateFields()
function DynArrayBlobSaveJson(TypeInfo: PRttiInfo; BlobValue: pointer; BlobLen: PtrInt): RawUtf8;
Serialize a dynamic array content, supplied as raw binary buffer, as JSON
- Value shall be set to the source dynamic array field
- is just a wrapper around TJsonWriter.AddDynArrayJson(), creating a temporary TDynArray wrapper on the stack
- to be used e.g. for custom record JSON serialization, within a TDynArrayJsonCustomWriter callback or Rtti.RegisterFromText()
function DynArrayLoadJson(var Value; const Json: RawUtf8; TypeInfo: PRttiInfo; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): boolean; overload;
Fill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson, which won't be modified
- this overloaded function will make a private copy before parsing it, so is safe with a read/only or shared string - but slightly slower
function DynArrayLoadJson(var Value; Json: PUtf8Char; TypeInfo: PRttiInfo; EndOfObject: PUtf8Char = nil; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): PUtf8Char; overload;
Fill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson with or without twoNonExpandedArrays layout
- Value shall be set to the target dynamic array field
- return a pointer at the end of the data read from JSON, nil in case of an invalid input buffer
- could be used e.g. for custom record JSON unserialization, within a TDynArrayJsonCustomReader callback
- warning: the JSON buffer will be modified in-place during process - use a temporary copy if you need to access it later or if the string comes from a constant (refcount=-1) - see e.g. the overloaded DynArrayLoadJson()
- some numbers on a Core i5-13500, extracted from our regression tests:
DynArrayLoadJson exp in 32.86ms i.e. 4.7M rows/s, 596.5 MB/s DynArrayLoadJson non exp in 22.46ms i.e. 6.9M rows/s, 383.7 MB/s
function DynArraySaveJson(const Value; TypeInfo: PRttiInfo; EnumSetsAsText: boolean = false): RawUtf8;
Serialize a dynamic array content as JSON
- Value shall be set to the source dynamic array field
- is just a wrapper around TJsonWriter.AddDynArrayJson(), creating a temporary TDynArray wrapper on the stack
- to be used e.g. for custom record JSON serialization, within a TDynArrayJsonCustomWriter callback or Rtti.RegisterFromText() (following EnumSetsAsText optional parameter for nested enumerates and sets)
function Expect(var P: PUtf8Char; Pattern: PUtf8Char; PatternLen: PtrInt): boolean;
PatternLen = 11 chars quickly check if an UTF-8 buffer start with the supplied Pattern
- PatternLen is at least 8 bytes long, typically FIELDCOUNT_PATTERN, ROWCOUNT_PATTERN or VALUES_PATTERN constants
- defined here for TDocVariantData.InitArrayFromResults
function FormatJson(const Format: RawUtf8; const Args, Params: array of const): RawUtf8;
Fast Format() function replacement, handling % but also ? parameters as JSON
- will include Args[] for every % in Format
- will include Params[] for every ? in Format, as their JSON value, with proper JSON double quotes and escaping for strings
- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
- is a wrapper around FormatParams(Format, Args, Params, true, result);
procedure FormatParams(const Format: RawUtf8; const Args, Params: array of const; JsonFormat: boolean; var Result: RawUtf8);
Fast Format() function replacement, handling % and ? parameters
- call rather FormatSql() and FormatJson() wrappers instead
- resulting string has no length limit and uses fast concatenation
- any supplied TObject instance will be written as their class name
function FormatSql(const Format: RawUtf8; const Args, Params: array of const): RawUtf8;
Fast Format() function replacement, handling % but also ? inlined parameters
- will include Args[] for every % in Format
- will include Params[] for every ? in Format, as "inlined" ORM or DB values, e.g. :(1234): for numbers, and :('quoted '' string'): for text
- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
- is a wrapper around FormatParams(Format, Args, Params, false, result);
function FormatUtf8(const Format: RawUtf8; const Args, Params: array of const; JsonFormat: boolean = false): RawUtf8; overload;
Rather call FormatSql() and FormatJson() functions
function GetFieldCountExpanded(P: PUtf8Char): integer;
Low-level parsing of the first expanded JSON object to guess fields count
function GetFirstJsonToken(P: PUtf8Char): TJsonToken;
Returns the JSON type of a supplied #0 ended buffer
- will move to the first non-space char, then returns its JSON_TOKENS[] value
- for valid JSON, is likely to return jtDoubleQuote, jtFirstDigit, jtNullFirstChar, jtTrueFirstChar, jtFalseFirstChar, jtObjectStart or jtArrayStart
function GetJsonField(P: PUtf8Char; out PDest: PUtf8Char; WasString: PBoolean = nil; EndOfObject: PUtf8Char = nil; Len: PInteger = nil): PUtf8Char;
Decode a JSON field value in-place from an UTF-8 encoded text buffer
- compatibility wrapper around TGetJsonField.GetJsonField method
function GetJsonFieldOrObjectOrArray(var Json: PUtf8Char; WasString: PBoolean = nil; EndOfObject: PUtf8Char = nil; HandleValuesAsObjectOrArray: boolean = false; NormalizeBoolean: boolean = true; Len: PInteger = nil): PUtf8Char;
Decode a JSON content from an UTF-8 encoded buffer
- compatibility wrapper around TGetJsonField.GetJsonFieldOrObjectOrArray
procedure GetJsonItemAsRawJson(var P: PUtf8Char; var result: RawJson; EndOfObject: PAnsiChar = nil);
Retrieve the next JSON item as a RawJson undecoded variable
- P buffer can be either any JSON item, i.e. a string, a number or even a JSON array (ending with ]) or a JSON object (ending with })
- EndOfObject (if not nil) is set to the JSON value end char (',' ':' or '}')
- input buffer is not modified in-place, since result is directly copied
function GetJsonItemAsRawUtf8(var P: PUtf8Char; var output: RawUtf8; WasString: PBoolean = nil; EndOfObject: PUtf8Char = nil): boolean;
Retrieve the next JSON item as a RawUtf8 decoded buffer
- P buffer can be either any JSON item, i.e. a string, a number or even a JSON array (ending with ]) or a JSON object (ending with })
- EndOfObject (if not nil) is set to the JSON value end char (',' ':' or '}')
- just calls TGetJsonField, and create a new RawUtf8 from the returned value, after proper string unescape (with WasString^=true)
- warning: input buffer is modified in-place during output value parsing
function GetJsonObjectOrArray(P: PUtf8Char; EndOfObject: PUtf8Char; Len: PInteger = nil): PUtf8Char;
Decode a JSON object or array from an UTF-8 encoded buffer
- as called by GetJsonFieldOrObjectOrArray() for HandleValuesAsObjectOrArray
- return the position of the next JSON item (with EndOfObject and optionally Len^ properly set) or nil on parsing error
function GetJsonPropName(var Json: PUtf8Char; Len: PInteger = nil; NoJsonUnescape: boolean = false): PUtf8Char;
Decode a JSON field name in an UTF-8 encoded buffer
- this function decodes in the P^ buffer memory itself (no memory allocation or copy), for faster process - so take care that P^ is not shared
- it will return the property name, with an ending #0, and "..." content properly unescaped unless NoJsonUnescape is set to true
- returns nil on error
- this function will handle strict JSON property name (i.e. a "string"), but also MongoDB extended syntax, e.g. {age:{$gt:18}} or {'people.age':{$gt:18}} see @http://docs.mongodb.org/manual/reference/mongodb-extended-json
procedure GetJsonPropNameShort(var P: PUtf8Char; out PropName: ShortString);
Decode a JSON field name in an UTF-8 encoded ShortString variable
- this function would left the P^ buffer memory untouched, so may be safer than the overloaded GetJsonPropName() function in some cases
- it will return the property name as a local UTF-8 encoded ShortString, or PropName='' on error
- this function won't unescape the property name, as strict JSON (i.e. a "st\"ring")
- but it will handle MongoDB syntax, e.g. {age:{$gt:18}} or {'people.age':{$gt:18}} see @http://docs.mongodb.org/manual/reference/mongodb-extended-json
function GetNextJsonToken(var P: PUtf8Char; strict: boolean = false; DocCount: PInteger = nil): TJsonToken;
Validate the supplied #0 ended buffer and returns its JSON type
- on parsing error, returns P=nil and jtNone
- will move P to the next JSON item, and return the JSON token kind, e.g. jtArrayStart, jtObjectStart, jtDoubleQuote or jtFirstDigit
- will allow comments and extended MongoDB JSON syntax unless Strict=true
- optionally return the number of nested items for jtArrayStart/jtObjectStart
function GetSetNameValue(Info: PRttiInfo; var P: PUtf8Char; out EndOfObject: AnsiChar): QWord; overload;
Helper to retrieve the bit mapped integer value of a set from its JSON text
- overloaded function using the RTTI
function GetSetNameValue(Names: PShortString; MinValue, MaxValue: integer; var P: PUtf8Char; out EndOfObject: AnsiChar): QWord; overload;
Helper to retrieve the bit mapped integer value of a set from its JSON text
- Names and MaxValue should be retrieved from RTTI
- if supplied P^ is a JSON integer number, will read it directly
- if P^ maps some ["item1","item2"] content, would fill all matching bits
- if P^ contains ['*'], would fill all bits
- returns P=nil if reached prematurely the end of content, or returns the value separator (e.g. , or }) in EndOfObject (like GetJsonField)
function GetValueObject(Instance: TObject; const Path: RawUtf8; out Value: variant): boolean;
Get any (potentially nested) object property by path
- complex values (e.g. dynamic array properties) will be returned as TDocVariant after JSON conversion
function GotoEndJsonItem(P: PUtf8Char; PMax: PUtf8Char = nil): PUtf8Char;
Reach position just after the current JSON item in the supplied UTF-8 buffer
- buffer can be either any JSON item, i.e. a string, a number or even a JSON array (ending with ]) or a JSON object (ending with })
- returns nil if the specified buffer is not valid JSON content
- returns the position in buffer just after the item excluding the separator character - i.e. result^ may be ',','}',']'
- will allow comments and extended MongoDB JSON syntax - use GotoEndJsonItemStrict() if you expect a more standard JSON parsing
function GotoEndJsonItemStrict(P: PUtf8Char; PMax: PUtf8Char = nil): PUtf8Char;
Reach position just after the current JSON item in the supplied UTF-8 buffer
- in respect to GotoEndJsonItem(), this function will validate for strict JSON simple values, i.e. real numbers or only true/false/null constants, and refuse commens or MongoDB extended syntax like {age:{$gt:18}}
- numbers and escaped strings are not fully validated, just their charset
function GotoEndJsonItemString(P: PUtf8Char): PUtf8Char;
Reach position just after the current JSON string in the supplied UTF-8 buffer
- will first ensure that P^='"' then process like GotoEndJsonItem()
function GotoEndOfJsonString(P: PUtf8Char): PUtf8Char;
Get the next character after a quoted buffer
- the first character in P^ must be "
- it will return the latest " position, ignoring \" within
- caller should check that return PUtf8Char is indeed a "
function GotoFieldCountExpanded(P: PUtf8Char): PUtf8Char;
Low-level prepare GetFieldCountExpanded() parsing returning '{' or ']'
function GotoNextJsonItem(P: PUtf8Char; var EndOfObject: AnsiChar): PUtf8Char; overload;
Reach the position of the next JSON item in the supplied UTF-8 buffer
- similar to the GotoNextJsonItem() with NumberOfItemsToJump=1
function GotoNextJsonItem(P: PUtf8Char; NumberOfItemsToJump: cardinal = 1; EndOfObject: PAnsiChar = nil; PMax: PUtf8Char = nil; Strict: boolean = false): PUtf8Char; overload;
Reach the position of the next JSON item(s) in the supplied UTF-8 buffer
- buffer can be either any JSON item, i.e. a string, a number or even a JSON array (ending with ]) or a JSON object (ending with })
- returns nil if the specified number of items is not available in buffer
- returns the position in buffer after the item including the separator character (optionally in EndOfObject) - i.e. result will be at the start of the next object, and EndOfObject may be ',','}',']'
procedure IgnoreComma(var P: PUtf8Char);
Simple method to go after the next ',' character
function IsNotExpandedBuffer(var P: PUtf8Char; PEnd: PUtf8Char; var FieldCount, RowCount: PtrInt): boolean;
Parse JSON content in not-expanded format
- i.e. stored as
{"fieldCount":2,"values":["f1","f2","1v1",1v2,"2v1",2v2...],"rowCount":20}- search and extract "fieldCount" and "rowCount" field information
- defined here for TDocVariantData.InitArrayFromResults
function IsString(P: PUtf8Char): boolean;
Test if the supplied buffer is a "string" value or a numerical value (floating point or integer), according to the characters within
- this version will recognize null/false/true as strings
- e.g. IsString('0')=false, IsString('abc')=true, IsString('null')=true
function IsStringJson(P: PUtf8Char): boolean;
Test if the supplied buffer is a "string" value or a numerical value (floating or integer), according to the JSON encoding schema
- this version will NOT recognize JSON null/false/true as strings
- e.g. IsStringJson('0')=false, IsStringJson('abc')=true, but IsStringJson('null')=false
- will follow the JSON definition of number, i.e. '0123' is a string (i.e. '0' is excluded at the begining of a number) and '123' is not a string
function IsValidJson(P: PUtf8Char; len: PtrInt; strict: boolean = false): boolean; overload;
Test if the supplied text buffer seems to be a correct (extended) JSON value
- will allow comments and extended MongoDB JSON syntax unless Strict=true
- numbers, escaped strings and commas are wild guessed, for performance
function IsValidJson(const s: RawUtf8; strict: boolean = false): boolean; overload;
Test if the supplied text seems to be a correct (extended) JSON value
- will allow comments and extended MongoDB JSON syntax unless Strict=true
- numbers, escaped strings and commas are wild guessed, for performance
function IsValidJsonBuffer(P: PUtf8Char; strict: boolean = false): boolean;
Test if the supplied #0 ended buffer is a correct (extended) JSON value
- will allow comments and extended MongoDB JSON syntax unless Strict=true
- numbers, escaped strings and commas are wild guessed, for performance
function JsonArrayCount(P: PUtf8Char; PMax: PUtf8Char = nil; Strict: boolean = false): integer;
Compute the number of elements of a JSON array
- this will handle any kind of arrays, including those with nested JSON objects or arrays
- incoming P^ should point to the first char AFTER the initial '[' (which may be a closing ']')
- returns 0 if the supplied input is invalid, or the number of identified items in the JSON array buffer
- if PMax is set, will abort after this position, and return the current counted number of items as negative, which could be used as initial allocation before the loop - typical use in this case is e.g.
cap := abs(JsonArrayCount(P, P + JSON_PREFETCH));
- some performance numbers on a Core i5-13400:
JsonArrayCount(P) in 10.95ms i.e. 14.3M/s, 1.7 GB/s
JsonArrayCount(P,PMax) in 11.05ms i.e. 14.1M/s, 1.7 GB/sfunction JsonArrayDecode(P: PUtf8Char; out Values: TPUtf8CharDynArray): boolean;
Retrieve the positions of all elements of a JSON array
- this will handle any kind of arrays, including those with nested JSON objects or arrays
- warning: incoming P^ should point to the first char AFTER the initial '[' (which may be a closing ']') - calling e.g. NextNotSpaceCharIs()
- returns false if the supplied input is invalid
- returns true on success, with Values[] pointing to each unescaped value, may be a JSON string, object, array of constant
function JsonArrayItem(P: PUtf8Char; Index: integer): PUtf8Char;
Go to the #nth item of a JSON array
- implemented via a fast SAX-like approach: the input buffer is not changed, nor no memory buffer allocated neither content copied
- returns nil if the supplied index is out of range
- returns a pointer to the index-nth item in the JSON array (first index=0)
- this will handle any kind of arrays, including those with nested JSON objects or arrays
- incoming P^ should point to the first initial '[' char
procedure JsonBufferReformat(P: PUtf8Char; out result: RawUtf8; Format: TTextWriterJsonFormat = jsonHumanReadable);
Formats and indents a JSON array or document to the specified layout
- just a wrapper around TJsonWriter.AddJsonReformat() method
- WARNING: the JSON buffer is decoded in-place, so P^ WILL BE modified
function JsonBufferReformatToFile(P: PUtf8Char; const Dest: TFileName; Format: TTextWriterJsonFormat = jsonHumanReadable): boolean;
Formats and indents a JSON array or document as a file
- just a wrapper around TJsonWriter.AddJsonReformat() method
- WARNING: the JSON buffer is decoded in-place, so P^ WILL BE modified
procedure JsonBufferToXML(P: PUtf8Char; const Header, NameSpace: RawUtf8; out result: RawUtf8);
Convert a JSON array or document into a simple XML content
- just a wrapper around TJsonWriter.AddJsonToXML, with an optional header before the XML converted data (e.g. XMLUTF8_HEADER), and an optional name space content node which will nest the generated XML data (e.g. '<contents xmlns="http://www.w3.org/2001/XMLSchema-instance">') - the corresponding ending token will be appended after (e.g. '</contents>')
- WARNING: the JSON buffer is decoded in-place, so P^ WILL BE modified
function JsonDecode(P: PUtf8Char; const Names: array of RawUtf8; Values: PValuePUtf8CharArray; HandleValuesAsObjectOrArray: boolean = false): PUtf8Char; overload;
Decode the supplied UTF-8 JSON object for the supplied field names
- data will be set in Values, according to the Names supplied e.g.
JsonDecode(P,['name','year'],Values) -> Values[0]^='John'; Values[1]^='1972';
- if any supplied name wasn't found its corresponding Values[] will be nil
- this procedure will decode the JSON content in-memory, i.e. the PUtf8Char array is created inside P, which is therefore modified: make a private copy first if you want to reuse the JSON content
- if HandleValuesAsObjectOrArray is TRUE, then this procedure will handle JSON arrays or objects
- if ValuesLen is set, ValuesLen[] will contain the length of each Values[]
- returns a pointer to the next content item in the JSON buffer
function JsonDecode(P: PUtf8Char; Names: PPUtf8CharArray; NamesCount: integer; Values: PValuePUtf8CharArray; HandleValuesAsObjectOrArray: boolean = false): PUtf8Char; overload;
Decode the supplied UTF-8 JSON object for the supplied field names
- overloaded function expecting the names supplied as a constant array
- slightly faster than the one using "const Names: array of RawUtf8"
function JsonDecode(P: PUtf8Char; out Values: TNameValuePUtf8CharDynArray; HandleValuesAsObjectOrArray: boolean = false): PUtf8Char; overload;
Decode the supplied UTF-8 JSON object into an array of name/value pairs
- this procedure will decode the JSON content in-memory, i.e. the PUtf8Char array is created inside JSON, which is therefore modified: make a private copy first if you want to reuse the JSON content
- the supplied JSON buffer should stay available until Name/Value pointers from returned Values[] are accessed
- if HandleValuesAsObjectOrArray is TRUE, then this procedure will handle JSON arrays or objects
- support enhanced JSON syntax, e.g. '{name:'"John",year:1972}' is decoded just like '{"name":'"John","year":1972}'
function JsonDecode(var Json: RawUtf8; const aName: RawUtf8 = 'result'; WasString: PBoolean = nil; HandleValuesAsObjectOrArray: boolean = false): RawUtf8; overload;
Decode the supplied UTF-8 JSON object for the one supplied field name
- this function will decode the JSON content in-memory, so will unescape it in-place: it must be called only once with the same JSON data
function JsonDecode(Json: PUtf8Char; const aName: RawUtf8; WasString: PBoolean; HandleValuesAsObjectOrArray: boolean): RawUtf8; overload;
Decode the supplied UTF-8 JSON object for the one supplied field name
- this function will decode and modify the input JSON buffer in-place
procedure JsonDecode(var Json: RawUtf8; const Names: array of RawUtf8; Values: PValuePUtf8CharArray; HandleValuesAsObjectOrArray: boolean = false); overload;
Decode the supplied UTF-8 JSON content for the supplied names
- data will be set in Values, according to the Names supplied e.g.
JsonDecode(JSON,['name','year'],@Values) -> Values[0].Value='John'; Values[1].Value='1972';
- if any supplied name wasn't found its corresponding Values[] will be nil
- this procedure will decode the JSON content in-memory, i.e. the PUtf8Char array is created inside JSON, which is therefore modified: make a private copy first if you want to reuse the JSON content
- if HandleValuesAsObjectOrArray is TRUE, then this procedure will handle JSON arrays or objects
- support enhanced JSON syntax, e.g. '{name:'"John",year:1972}' is decoded just like '{"name":'"John","year":1972}'
procedure JsonDecode(var Json: RawJson; const Names: array of RawUtf8; Values: PValuePUtf8CharArray; HandleValuesAsObjectOrArray: boolean = false); overload;
Decode the supplied UTF-8 JSON content for the supplied names
- an overloaded function when the JSON is supplied as a RawJson variable
function JsonEncode(const Format: RawUtf8; const Args, Params: array of const): RawUtf8; overload;
Encode the supplied (extended) JSON content, with parameters, as an UTF-8 valid JSON object content
- in addition to the JSON RFC specification strict mode, this method will handle some BSON-like extensions, e.g. unquoted field names:
aJson := JsonEncode('{id:?,%:{name:?,birthyear:?}}',['doc'],[10,'John',1982]);
- you can use nested _Obj() / _Arr() instances
aJson := JsonEncode('{%:{$in:[?,?]}}',['type'],['food','snack']); aJson := JsonEncode('{type:{$in:?}}',[],[_Arr(['food','snack'])]); // will both return '{"type":{"$in":["food","snack"]}}')
- if the mormot.db.nosql.bson unit is used in the application, the MongoDB Shell syntax will also be recognized to create TBsonVariant, like
new Date() ObjectId() MinKey MaxKey /<jRegex>/<jOptions>
see @http://docs.mongodb.org/manual/reference/mongodb-extended-json
aJson := JsonEncode('{name:?,field:/%/i}',['acme.*corp'],['John'])) // will return '{"name":"John","field":{"$regex":"acme.*corp","$options":"i"}}'
- will call internally _JsonFastFmt() to create a temporary TDocVariant with all its features - so is slightly slower than other JsonEncode* functions
function JsonEncode(const NameValuePairs: array of const): RawUtf8; overload;
Encode the supplied data as an UTF-8 valid JSON object content
- data must be supplied two by two, as Name,Value pairs, e.g.
JsonEncode(['name','John','year',1972]) = '{"name":"John","year":1972}'
- or you can specify nested arrays or objects with '['..']' or '{'..'}':
J := JsonEncode(['doc','{','name','John','abc','[','a','b','c',']','}','id',123]); assert(J='{"doc":{"name":"John","abc":["a","b","c"]},"id":123}');
- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
- you can pass nil as parameter for a null JSON value
function JsonEncodeArrayDouble( const Values: array of double): RawUtf8; overload;
Encode the supplied floating-point array data as a valid JSON array
function JsonEncodeArrayInteger( const Values: array of integer): RawUtf8; overload;
Encode the supplied integer array data as a valid JSON array
function JsonEncodeArrayOfConst(const Values: array of const; WithoutBraces: boolean = false): RawUtf8; overload;
Encode the supplied array data as a valid JSON array content
- if WithoutBraces is TRUE, no [ ] will be generated
- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
procedure JsonEncodeArrayOfConst(const Values: array of const; WithoutBraces: boolean; var result: RawUtf8); overload;
Encode the supplied array data as a valid JSON array content
- if WithoutBraces is TRUE, no [ ] will be generated
- note that, due to a Delphi compiler limitation, cardinal values should be type-casted to Int64() (otherwise the integer mapped value will be converted)
function JsonEncodeArrayUtf8( const Values: array of RawUtf8): RawUtf8; overload;
Encode the supplied RawUtf8 array data as an UTF-8 valid JSON array content
procedure JsonEncodeNameSQLValue(const Name, SQLValue: RawUtf8; var result: RawUtf8);
Encode as JSON {"name":value} object, from a potential SQL quoted value
- will unquote the SQLValue using TJsonWriter.AddQuotedStringAsJson()
function JsonFileToObject(const JsonFile: TFileName; var ObjectInstance; TObjectListItemClass: TClass = nil; Options: TJsonParserOptions = []; Interning: TRawUtf8Interning = nil): boolean;
Fill the object properties from a JSON file content
- ObjectInstance must be an existing TObject instance
- this function will call RemoveCommentsFromJson() before process
function JsonObjectAsJsonArrays(Json: PUtf8Char; out keys, values: RawUtf8): integer;
Convert one JSON object into two JSON arrays of keys and values
- i.e. makes the following transformation:
{key1:value1,key2,value2...} -> [key1,key2...] + [value1,value2...]- this function won't allocate any memory during its process, nor modify the JSON input buffer
- is the reverse of the TJsonWriter.AddJsonArraysAsJsonObject() method
- used e.g. by TSynDictionary.LoadFromJson
- returns the number of items parsed and stored into keys/values, -1 on error parsing the input JSON buffer
function JsonObjectByPath(JsonObject, PropPath: PUtf8Char): PUtf8Char;
Go to a property of a JSON object, by its full path, e.g. 'parent.child'
- implemented via a fast SAX-like approach: the input buffer is not changed, nor no memory buffer allocated neither content copied
- PropPath is search case-insensitively as 'parent.child' or 'parent.ch*'
- returns nil if the supplied property path does not exist
- returns a pointer to the matching item value in the JSON object
- this will handle any kind of objects, including those with nested JSON objects or arrays
- incoming P^ should point to the first initial '{' char
function JsonObjectItem(P: PUtf8Char; const PropName: RawUtf8; PropNameFound: PRawUtf8 = nil): PUtf8Char; overload;
Go to a named property of a JSON object
- implemented via a fast SAX-like approach: the input buffer is not changed, nor no memory buffer allocated neither content copied
- PropName is search case-insensitively as 'propertyname' or 'property*'
- returns nil if the supplied property name does not exist
- returns a pointer to the matching item value in the JSON object
- this will handle any kind of objects, including those with nested JSON objects or arrays
- incoming P^ should point to the first initial '{' char
function JsonObjectItem(P: PUtf8Char; PropName: PUtf8Char; PropNameLen: PtrInt; PropNameFound: PRawUtf8): PUtf8Char; overload;
Go to a buffer-named property of a JSON object
- as called by overloaded JsonObjectItem()
function JsonObjectPropCount(P: PUtf8Char; PMax: PUtf8Char = nil; Strict: boolean = false): PtrInt;
Compute the number of fields in a JSON object
- this will handle any kind of objects, including those with nested JSON documents, and also comments or MongoDB extended syntax (unless Strict=true)
- warning: incoming P^ should point to the first char AFTER the initial '{' (which may be a closing '}')
- will abort if P reaches PMax (if not nil), and return the current counted number of items as negative, which could be used as initial allocation before a parsing loop - typical use in this case is e.g.
cap := abs(JsonObjectPropCount(P, P + JSON_PREFETCH));
function JsonObjectsByPath(JsonObject, PropPath: PUtf8Char): RawUtf8;
Return all matching properties of a JSON object
- here the PropPath could be a comma-separated list of case-insensitive full paths, e.g. 'Prop1,Prop2' or 'Obj1.Obj2.Prop*,Obj1.Prop1'
- returns '' if no property did match
- returns a JSON object of all matching properties
- this will handle any kind of objects, including those with nested JSON objects or arrays
- incoming P^ should point to the first initial '{' char
function JsonPropNameValid(P: PUtf8Char): boolean;
Returns TRUE if the given text buffer contains simple characters as recognized by JSON extended syntax
- follow GetJsonPropName and GotoNextJsonObjectOrArray expectations
function JsonReformat(const Json: RawUtf8; Format: TTextWriterJsonFormat = jsonHumanReadable): RawUtf8;
Formats and indents a JSON array or document to the specified layout
- just a wrapper around TJsonWriter.AddJsonReformat, making a private of the supplied JSON buffer (so that JSON content would stay untouched)
function JsonReformatToFile(const Json: RawUtf8; const Dest: TFileName; Format: TTextWriterJsonFormat = jsonHumanReadable): boolean;
Formats and indents a JSON array or document as a file
- just a wrapper around TJsonWriter.AddJsonReformat, making a private of the supplied JSON buffer (so that JSON content would stay untouched)
function JsonRetrieveObjectRttiCustom(var Json: PUtf8Char; AndGlobalFindClass: boolean): TRttiCustom;
Retrieve a class Rtti, as saved by ObjectToJson(...,[...,woStoreClassName,...]);
- JSON input should be either 'null', either '{"ClassName":"TMyClass",...}'
- calls IdemPropName/JsonRetrieveStringField so input buffer won't be modified, but caller should ignore this "ClassName" property later on
- the corresponding class shall have been previously registered by Rtti.RegisterClass(), in order to retrieve the class type from it name - or, at least, by the RTL Classes.RegisterClass() function, if AndGlobalFindClass parameter is left to default true so that RTL Classes.FindClass() is called
function JsonRetrieveStringField(P: PUtf8Char; out Field: PUtf8Char; out FieldLen: integer; ExpectNameField: boolean): PUtf8Char;
Retrieve a pointer to JSON string field content, without unescaping it
- returns either ':' for name field, or } , for value field
- returns nil on JSON content error
- this function won't touch the JSON buffer, so you can call it before using in-place escape process via JsonDecode() or TGetJsonField
function JsonSettingsToObject(const JsonContent: RawUtf8; Instance: TObject): boolean;
Parse the supplied JSON with some tolerance about Settings format
- will make a TSynTempBuffer copy for parsing, and un-comment it
- returns true if the supplied JSON was successfully retrieved
- returns false on error
function JsonToNewObject(var From: PUtf8Char; var Valid: boolean; Options: TJsonParserOptions = []; Interning: TRawUtf8Interning = nil): TObject;
Create a new object instance, as saved by ObjectToJson(...,[...,woStoreClassName,...]);
- JSON input should be either 'null', either '{"ClassName":"TMyClass",...}'
- woStoreClassName option shall have been used at ObjectToJson() call
- and the corresponding class shall have been previously registered by Rtti.RegisterClass() to retrieve the class type from it name
- the data inside From^ is modified in-place (unescaped and transformed): don't call JsonToObject(pointer(JSONRawUtf8)) but makes a temporary copy of the JSON text buffer before calling this function, if want to reuse it later
function JsonToObject(var ObjectInstance; From: PUtf8Char; out Valid: boolean; TObjectListItemClass: TClass = nil; Options: TJsonParserOptions = []; Interning: TRawUtf8Interning = nil): PUtf8Char;
Read an object properties, as saved by ObjectToJson function
- ObjectInstance must be an existing TObject instance
- the data inside From^ is modified in-place (unescaped and transformed): calling JsonToObject(pointer(JSONRawUtf8)) will change the JSONRawUtf8 variable content, which may not be what you expect - consider using the ObjectLoadJson() function instead
- handle integer, Int64, enumerate (including boolean), set, floating point, TDateTime, TCollection, TStrings, TRawUtf8List, variant, and string properties (excluding ShortString, but including WideString and UnicodeString under Delphi 2009+)
- TList won't be handled since it may leak memory when calling TList.Clear
- won't handle TObjectList (even if ObjectToJson is able to serialize them) since has no way of knowing the object type to add (TCollection.Add is missing), unless: 1. you set the TObjectListItemClass property as expected, and provide a TObjectList object, or 2. woStoreClassName option has been used at ObjectToJson() call and the corresponding classes have been previously registered by Rtti.RegisterClass()
- will clear any previous TCollection objects, and convert any null JSON basic type into nil - e.g. if From='null', will call FreeAndNil(Value)
- you can add some custom (un)serializers for ANY class, via mormot.core.json TRttiJson.RegisterCustomSerializer() class method
- set Valid=TRUE on success, Valid=FALSE on error, and the main function will point in From at the syntax error place (e.g. on any unknown property name)
- caller should explicitly perform a SetDefaultValuesObject(Value) if the default values are expected to be set before JSON parsing
function JsonToXML(const Json: RawUtf8; const Header: RawUtf8 = XMLUTF8_HEADER; const NameSpace: RawUtf8 = ''): RawUtf8;
Convert a JSON array or document into a simple XML content
- just a wrapper around TJsonWriter.AddJsonToXML, making a private copy of the supplied JSON buffer using TSynTempBuffer (so that JSON content would stay untouched)
- the optional header is added at the beginning of the resulting string
- an optional name space content node could be added around the generated XML, e.g. '<content>'
function JsonUnicodeEscape(const s: RawUtf8): RawUtf8;
{$ifdef HASINLINE}inline;{$endif} ensure all UTF-8 Unicode glyphs are escaped as \u#### UTF-16 JSON
- this will work at raw UTF-8 text level: if your input is true JSON, consider using JsonReformat(s, jsonEscapeUnicode) instead
function JsonUnicodeEscapeToUtf8(var D: PUtf8Char; P: PUtf8Char): PUtf8Char;
UTF-8 decode one or two \u#### JSON escaped codepoints into Dest
- P^ should point at 'u1234' just after \u1234
- return ending P position, maybe after another \u#### UTF-16 surrogate char
function JsonUnicodeUnEscape(const s: RawUtf8): RawUtf8;
Ensure all \u#### UTF-16 JSON are decoded into plain UTF-8 content
- this will work at raw UTF-8 text level: if your input is true JSON, consider using JsonReformat(s, jsonNoEscapeUnicode) instead
function LoadJson(var Value; const Json: RawUtf8; TypeInfo: PRttiInfo; EndOfObject: PUtf8Char = nil; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): boolean;
Unserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson
- this overloaded function will make a private copy before parsing it, so is safe with a read/only or shared string - but slightly slower
function LoadJsonInPlace(var Value; Json: PUtf8Char; TypeInfo: PRttiInfo; EndOfObject: PUtf8Char = nil; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): PUtf8Char;
Unserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson
- same implementation than GetDataFromJson() global low-level function
- returns nil on error, or the end of buffer on success
- warning: the JSON buffer will be modified in-place during process - use LoadJson() instead or a make temporary copy if you need to access it later
function NeedsJsonEscape(P: PUtf8Char): boolean; overload;
Returns TRUE if the given text buffers would be escaped when written as JSON
- e.g. if contains " or \ characters, as defined by http://www.ietf.org/rfc/rfc4627.txt
function NeedsJsonEscape(const Text: RawUtf8): boolean; overload;
Returns TRUE if the given text buffers would be escaped when written as JSON
- e.g. if contains " or \ characters, as defined by http://www.ietf.org/rfc/rfc4627.txt
function NeedsJsonEscape(P: PUtf8Char; PLen: integer): boolean; overload;
Returns TRUE if the given text buffers would be escaped when written as JSON
- e.g. if contains " or \ characters, as defined by http://www.ietf.org/rfc/rfc4627.txt
function NotExpandedBufferRowCountPos(P, PEnd: PUtf8Char): PUtf8Char;
Efficient retrieval of the number of rows in non-expanded layout
- search for "rowCount": at the end of the JSON buffer
function ObjArrayToJson(const aObjArray; aOptions: TTextWriterWriteObjectOptions = [woDontStoreDefault]): RawUtf8;
Wrapper to serialize a T*ObjArray dynamic array as JSON
- for proper serialization on Delphi 7-2009, use Rtti.RegisterObjArray()
function ObjectLoadJson(var ObjectInstance; const Json: RawUtf8; TObjectListItemClass: TClass = nil; Options: TJsonParserOptions = []; Interning: TRawUtf8Interning = nil): boolean;
Read an object properties, as saved by ObjectToJson function
- ObjectInstance must be an existing TObject instance
- this overloaded version will make a private copy of the supplied JSON content (via TSynTempBuffer), to ensure the original buffer won't be modified during process, before calling safely JsonToObject()
- will return TRUE on success, or FALSE if the supplied JSON was invalid
function ObjectsToJson(const Names: array of RawUtf8; const Values: array of TObject; Options: TTextWriterWriteObjectOptions = [woDontStoreDefault]): RawUtf8;
Will serialize set of TObject into its UTF-8 JSON representation
- follows ObjectToJson()/TJsonWriter.WriterObject() functions output
- if Names is not supplied, the corresponding class names would be used
function ObjectToJsonFile(Value: TObject; const JsonFile: TFileName; Options: TTextWriterWriteObjectOptions = [woHumanReadable]): boolean;
Persist a class instance into a JSON file
- returns TRUE on success, false on error (e.g. the file name is invalid or the file is existing and could not be overwritten)
- see ObjectToJson() as defined in momrot.core.text.pas
function ParseEndOfObject(P: PUtf8Char; out EndOfObject: AnsiChar): PUtf8Char;
Search the EndOfObject of a JSON buffer, just like TGetJsonField does
function PropertyFromJson(Prop: PRttiCustomProp; Instance: TObject; From: PUtf8Char; var Valid: boolean; Options: TJsonParserOptions = []; Interning: TRawUtf8Interning = nil): PUtf8Char;
Read an TObject published property, as saved by ObjectToJson() function
- will use direct in-memory reference to the object, or call the corresponding setter method (if any), creating a temporary instance
- unserialize the JSON input buffer via a call to JsonToObject()
- by default, a temporary instance will be created if a published field has a setter, and the instance is expected to be released later by the owner class: you can set the j2oSetterExpectsToFreeTempInstance option to let this method release it when the setter returns
function QuotedStrJson(const aText: RawUtf8): RawUtf8; overload;
Convert UTF-8 content into a JSON string
- with proper escaping of the content, and surounding " characters
procedure QuotedStrJson(P: PUtf8Char; PLen: PtrInt; var result: RawUtf8; const aPrefix: RawUtf8 = ''; const aSuffix: RawUtf8 = ''); overload;
Convert UTF-8 buffer into a JSON string
- with proper escaping of the content, and surounding " characters
procedure QuotedStrJson(const aText: RawUtf8; var result: RawUtf8; const aPrefix: RawUtf8 = ''; const aSuffix: RawUtf8 = ''); overload;
Convert UTF-8 content into a JSON string
- with proper escaping of the content, and surounding " characters
function RecordLoadJson(var Rec; const Json: RawUtf8; TypeInfo: PRttiInfo; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): boolean; overload;
Fill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson
- this overloaded function will make a private copy before parsing it, so is safe with a read/only or shared string - but slightly slower
function RecordLoadJson(var Rec; Json: PUtf8Char; TypeInfo: PRttiInfo; EndOfObject: PUtf8Char = nil; CustomVariantOptions: PDocVariantOptions = nil; Tolerant: boolean = true; Interning: TRawUtf8Interning = nil): PUtf8Char; overload;
Fill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson
- will use default Base64 encoding over RecordSave() binary - or custom JSON format (as set by Rtti.RegisterFromText/TRttiJson.RegisterCustomSerializer or via enhanced RTTI), if available
- returns nil on error, or the end of buffer on success
- warning: the JSON buffer will be modified in-place during process - use a temporary copy if you need to access it later or if the string comes from a constant (refcount=-1) - see e.g. the overloaded RecordLoadJson()
function RecordSaveJson(const Rec; TypeInfo: PRttiInfo; EnumSetsAsText: boolean = false): RawUtf8;
Save record into its JSON serialization as saved by TJsonWriter.AddRecordJson
- will use default Base64 encoding over RecordSave() binary - or custom true JSON format (as set by Rtti.RegisterFromText/TRttiJson.RegisterCustomSerializer or via enhanced RTTI), if available (following EnumSetsAsText optional parameter for nested enumerates and sets)
procedure RemoveCommentsFromJson(P: PUtf8Char); overload;
Remove comments and trailing commas from a text buffer before passing it to a JSON parser
- handle two types of comments: starting from // till end of line or /* ..... */ blocks anywhere in the text content
- trailing commas is replaced by ' ', so resulting JSON is valid for parsers what not allows trailing commas (browsers for example)
- may be used to prepare configuration files before loading; for example we store server configuration in file config.json and put some comments in this file then code for loading is:
var cfg: RawUtf8; ... cfg := StringFromFile(Executable.ProgramFilePath + 'config.json'); RemoveCommentsFromJson(@cfg[1]); pLastChar := JsonToObject(obj, pointer(cfg), isvalid);
function RemoveCommentsFromJson(const s: RawUtf8): RawUtf8; overload;
Remove comments from a text buffer before passing it to JSON parser
- won't remove the comments in-place, but allocate a new string
function SaveJson(const Value; const TypeName: RawUtf8; Options: TTextWriterOptions = []): RawUtf8; overload;
Serialize most kind of content as JSON, using its RTTI and a type name
- could be used if you know the type name and not the TypeInfo()
- will use Rtti.RegisterTypeFromName() so the type should be known, i.e. be a simple type, or have been alredy registered
- returns '' if TypeName is not recognized
procedure SaveJson(const Value; TypeInfo: PRttiInfo; Options: TTextWriterOptions; var result: RawUtf8; ObjectOptions: TTextWriterWriteObjectOptions = []); overload;
Serialize most kind of content as JSON, using its RTTI
- is just a wrapper around TJsonWriter.AddTypedJson()
- so would handle tkClass, tkEnumeration, tkSet, tkRecord, tkDynArray, tkVariant kind of content - other kinds would return 'null'
- you can override serialization options if needed
function SaveJson(const Value; TypeInfo: PRttiInfo; EnumSetsAsText: boolean): RawUtf8; overload;
Serialize most kind of content as JSON, using its RTTI
- is just a wrapper around TJsonWriter.AddTypedJson()
function SaveJson(const Value; TypeInfo: PRttiInfo): RawUtf8; overload;
Serialize most kind of content as JSON, using its RTTI
function UrlDecodeObject(U: PUtf8Char; Upper: PAnsiChar; var ObjectInstance; Next: PPUtf8Char = nil; Options: TJsonParserOptions = []): boolean;
Decode a specified parameter compatible with URI encoding into its original object contents
- ObjectInstance must be an existing TObject instance
- will call internally JsonToObject() function to unserialize its content
- UrlDecodeExtended('price=20.45&where=LastName%3D%27M%C3%B4net%27','PRICE=',P,@Next) will return Next^='where=...' and P=20.45
- if Upper is not found, Value is not modified, and result is FALSE
- if Upper is found, Value is modified with the supplied content, and result is TRUE
function UrlEncodeJsonObject(const UriName, ParametersJson: RawUtf8; const PropNamesToIgnore: array of RawUtf8; IncludeQueryDelimiter: boolean = true): RawUtf8; overload;
Encode a JSON object UTF-8 buffer into URI parameters
- you can specify property names to ignore during the object decoding
- you can omit the leading query delimiter ('?') by setting IncludeQueryDelimiter=false
- overloaded function which will make a copy of the input JSON before parsing
function UrlEncodeJsonObject(const UriName: RawUtf8; ParametersJson: PUtf8Char; const PropNamesToIgnore: array of RawUtf8; IncludeQueryDelimiter: boolean = true): RawUtf8; overload;
Encode a JSON object UTF-8 buffer into URI parameters
- you can specify property names to ignore during the object decoding
- you can omit the leading query delimiter ('?') by setting IncludeQueryDelimiter=false
- warning: the ParametersJson input buffer will be modified in-place
procedure Utf16ToJsonUnicodeEscape(var B: PUtf8Char; c: PtrUint; tab: PByteToWord);
Encode one \u#### JSON escaped UTF-16 codepoint into Dest
DEFAULT_WRITEOPTIONS: array[boolean] of TTextWriterWriteObjectOptions = ( [woDontStoreDefault, woRawBlobAsBase64], [woDontStoreDefault, woDontStoreVoid, woRawBlobAsBase64]);
The options used by TObjArraySerializer, TInterfacedObjectFake and TServiceMethodExecute when serializing values as JSON
- used as DEFAULT_WRITEOPTIONS[DontStoreVoidJson]
- you can modify this global variable to customize the whole process
JSONPARSER_DEFAULTOPTIONS: TJsonParserOptions = [];
Default options for the JSON parser
- as supplied to LoadJson() with Tolerant=false
- defined as var, not as const, to allow process-wide override
JSONPARSER_DEFAULTORTOLERANTOPTIONS: array[boolean] of TJsonParserOptions = ( [], [jpoHandleCustomVariants, jpoIgnoreUnknownEnum, jpoIgnoreUnknownProperty, jpoIgnoreStringType, jpoAllowInt64Hex]);
Access default (false) or tolerant (true) JSON parser options
- to be used as JSONPARSER_DEFAULTORTOLERANTOPTIONS[tolerant]
JSONPARSER_TOLERANTOPTIONS: TJsonParserOptions = [jpoHandleCustomVariants, jpoIgnoreUnknownEnum, jpoIgnoreUnknownProperty, jpoIgnoreStringType, jpoAllowInt64Hex];
Some open-minded options for the JSON parser
- as supplied to LoadJson() with Tolerant=true
- won't block JSON unserialization due to some minor unexpected values
- used e.g. by TObjArraySerializer.CustomReader and TInterfacedObjectFake.FakeCall/TServiceMethodExecute.ExecuteJson methods
- defined as var, not as const, to allow process-wide override
JSON_CHARS: TJsonCharSet;
256-byte lookup table for fast branchless JSON parsing
- to be used e.g. as:
if jvJsonIdentifier in JSON_CHARS[P^] then ...
JSON_ESCAPE: array[byte] of byte;
256-byte lookup table for fast branchless JSON text escaping
- 0 = JSON_ESCAPE_NONE indicates no escape needed
- 1 = JSON_ESCAPE_ENDINGZERO indicates #0 (end of string)
- 2 = JSON_ESCAPE_UNICODEHEX should be escaped as \u00xx
- b,t,n,f,r,\," as escaped character for #8,#9,#10,#12,#13,\,"
JSON_PREFETCH: integer = 65536;
How many initial chars of a JSON array are parsed for intial capacity
- used e.g. by _JL_DynArray() and TDocVariantData.InitJsonInPlace()
- 64KB was found out empirically as a good value - but you can tune it
JSON_TOKENS: TJsonTokens;
256-byte lookup table for fast branchless initial character JSON parsing
JSON_UNESCAPE: array[AnsiChar] of AnsiChar;
256-byte lookup table for fast branchless JSON text un-escaping
- #0 = JSON_UNESCAPE_UNEXPECTED for unexpected #0 or control char
- #1 = JSON_UNESCAPE_UTF16 for '\u0123' UTF-16 pattern
- #8,#9,#10,#12,#13 as unescaped char from b,t,n,f,r
- other characters are litterals and should be written as such
SERVICELOG_WRITEOPTIONS: TTextWriterWriteObjectOptions = [woDontStoreDefault, woDontStoreVoid, woHideSensitivePersonalInformation];
The options used by TServiceFactoryServer.OnLogRestExecuteMethod
- you can modify this global variable to customize the whole process
SETTINGS_WRITEOPTIONS: TTextWriterWriteObjectOptions = [woHumanReadable, woStoreStoredFalse, woHumanReadableFullSetsAsStar, woHumanReadableEnumSetAsComment, woInt64AsHex];
The options used by TSynJsonFileSettings.SaveIfNeeded
- you can modify this global variable to customize the whole process