logo.png
mORMot2 API Reference

mormot.core.json.pas unit

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

1.1. Units used in the mormot.core.json unit

Unit NameDescription
mormot.core.baseFramework Core Shared Types and RTL-like Functions
mormot.core.buffersFramework Core Low-Level Memory Buffer Process
mormot.core.dataFramework Core Low-Level Data Processing Functions
mormot.core.datetimeFramework Core Low-Level Date and Time Support
mormot.core.osFramework Core Low-Level Wrappers to the Operating-System API
mormot.core.rttiFramework Core Low-Level Cross-Compiler RTTI Definitions
mormot.core.textFramework Core Low-Level Text Processing
mormot.core.unicodeFramework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion
mormot.core.variantsFramework Core Low-Level Variants / TDocVariant process

1.2. mormot.core.json class hierarchy

TTextDateWriterTJsonWriterTSynPersistentStoreTSynPersistentStoreJsonTSynPersistentLockTSynAutoCreateFieldsLockedTSynPersistentTSynCacheTSynAutoCreateFieldsTSynJsonFileSettingsTSynLockedTSynDictionaryTRttiCustomTRttiJsonTPersistentWithCustomCreateTPersistentAutoCreateFieldsTObjectTSynNameValueTJsonSaveContextTGetJsonFieldTJsonParserContextTInterfacedObjectWithCustomCreateTInterfacedObjectAutoCreateFieldsTInterfacedSerializableTInterfacedSerializableAutoCreateFieldsTInterfacedObjectTCollectionItemTCollectionItemAutoCreateFieldsIInterfaceISerializableESynExceptionESynDictionaryEJsonException
mormot.core.json class hierarchy

1.3. Objects implemented in the mormot.core.json unit

ObjectsDescription
EJsonExceptionException raised by this unit, in relation to raw JSON process
ESynDictionaryException raised during TSynDictionary process
ISerializableAbstract interface parent with common methods for JSON serialization
TCollectionItemAutoCreateFieldsAbstract TCollectionItem class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed
TGetJsonFieldEfficient JSON value parser / in-place decoder
TInterfacedObjectAutoCreateFieldsAbstract TInterfacedObject class, which will instantiate all its nested class published properties, then release them when freed
TInterfacedSerializableAbstract class parent with ISerializable methods for JSON serialization
TInterfacedSerializableAutoCreateFieldsAbstract ISerializable class parent with auto-create published fields
TJsonParserContextEfficient execution context of the JSON parser
TJsonSaveContextInternal stack-allocated structure for nested JSON serialization
TJsonWriterJSON-capable TTextWriter/TTextDateWriter inherited class
TNameValuePUtf8CharStore one name/value pair of raw UTF-8 content, from a JSON buffer
TPersistentAutoCreateFieldsAbstract TPersistent class, which will instantiate all its nested class published properties, then release them (and any T*ObjArray) when freed
TRttiJsonJSON-aware TRttiCustom class - used for global RttiCustom: TRttiCustomList
TSynAutoCreateFieldsOur own empowered TPersistentAutoCreateFields-like parent class
TSynAutoCreateFieldsLockedAdding locking methods to a TSynAutoCreateFields with virtual constructor
TSynCacheImplement a cache of some key/value pairs, e.g. to improve reading speed
TSynDictionaryThread-safe dictionary to store some values from associated keys
TSynJsonFileSettingsAbstract parent class able to store settings as JSON file
TSynNameValuePseudo-class used to store Name/Value RawUtf8 pairs
TSynNameValueItemStore one Name/Value pair, as used by TSynNameValue class
TSynPersistentStoreJsonImplement binary persistence and JSON serialization (not deserialization)

1.3.1. EJsonException

EJsonException = class(ESynException)

Exception raised by this unit, in relation to raw JSON process


1.3.2. TGetJsonField

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


1.3.3. TJsonWriter

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":


1.3.4. TSynNameValueItem

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


1.3.5. TSynNameValue

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


1.3.6. TSynCache

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


1.3.7. TSynPersistentStoreJson

TSynPersistentStoreJson = class(TSynPersistentStore)

Implement binary persistence and JSON serialization (not deserialization)


function SaveToJson(reformat: TTextWriterJsonFormat = jsonCompact): RawUtf8;

Serialize this instance as a JSON object


1.3.8. ESynDictionary

ESynDictionary = class(ESynException)

Exception raised during TSynDictionary process


1.3.9. TSynDictionary

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


1.3.10. TJsonSaveContext

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


1.3.11. TNameValuePUtf8Char

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


1.3.12. TJsonParserContext

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


1.3.13. TRttiJson

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


1.3.14. TPersistentAutoCreateFields

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


1.3.15. TSynAutoCreateFields

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


1.3.16. TSynAutoCreateFieldsLocked

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


1.3.17. TInterfacedObjectAutoCreateFields

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


1.3.18. ISerializable

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


1.3.19. TInterfacedSerializable

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


1.3.20. TInterfacedSerializableAutoCreateFields

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


1.3.21. TCollectionItemAutoCreateFields

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


1.3.22. TSynJsonFileSettings

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


1.4. Types implemented in the mormot.core.json unit

1.4.1. PInterfacedSerializable

PInterfacedSerializable = ^TInterfacedSerializable;

Points to a TInterfacedSerializable class instance


1.4.2. PJsonCharSet

PJsonCharSet = ^TJsonCharSet;

Points to a lookup table used for branch-less JSON parsing


1.4.3. PJsonTokens

PJsonTokens = ^TJsonTokens;

Points to a lookup table used for branch-less first char JSON parsing


1.4.4. PSynNameValue

PSynNameValue = ^TSynNameValue;

A reference pointer to a Name/Value RawUtf8 pairs storage


1.4.5. TInterfacedObjectAutoCreateFieldsClass

TInterfacedObjectAutoCreateFieldsClass = class of TInterfacedObjectAutoCreateFields;

Meta-class definition of TInterfacedObjectAutoCreateFields


1.4.6. TInterfacedSerializableClass

TInterfacedSerializableClass = class of TInterfacedSerializable;

Meta-class of the TInterfacedSerializable type


1.4.7. TJsonChar

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


1.4.8. TJsonCharSet

TJsonCharSet = array[AnsiChar] of TJsonChar;

Defines a lookup table used for branch-less JSON parsing


1.4.9. TJsonParserOption

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


1.4.10. TJsonParserOptions

TJsonParserOptions = set of TJsonParserOption;

Set of options for JsonParser() parsing process


1.4.11. TJsonToken

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


1.4.12. TJsonTokens

TJsonTokens = array[AnsiChar] of TJsonToken;

Defines a lookup table used for branch-less first char JSON parsing


1.4.13. TJsonToObjectOption

TJsonToObjectOption = TJsonParserOption;

Backward compatibility types redirections


1.4.14. TNameValuePUtf8CharDynArray

TNameValuePUtf8CharDynArray = array of TNameValuePUtf8Char;

Used e.g. by JsonDecode() overloaded function to returns name/value pairs


1.4.15. TOnClassJsonRead

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


1.4.16. TOnClassJsonWrite

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


1.4.17. TOnRttiJsonRead

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^


1.4.18. TOnRttiJsonWrite

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


1.4.19. TOnSynDictionary

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


1.4.20. TOnSynDictionaryCanDelete

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


1.4.21. TOnSynNameValueConvertRawUtf8

TOnSynNameValueConvertRawUtf8 = function( const text: RawUtf8): RawUtf8 of object;

Event handler used to convert on the fly some UTF-8 text content


1.4.22. TOnSynNameValueNotify

TOnSynNameValueNotify = procedure( const Item: TSynNameValueItem; Index: PtrInt) of object;

Callback event used by TSynNameValue


1.4.23. TRttiJsonLoad

TRttiJsonLoad = procedure(Data: pointer; var Ctxt: TJsonParserContext);

Internal function handler for JSON reading of any TRttiParserType value


1.4.24. TRttiJsonSave

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


1.4.25. TSynAutoCreateFieldsClass

TSynAutoCreateFieldsClass = class of TSynAutoCreateFields;

Meta-class definition of TSynAutoCreateFields


1.4.26. TSynAutoCreateFieldsLockedClass

TSynAutoCreateFieldsLockedClass = class of TSynAutoCreateFieldsLocked;

Meta-class definition of TSynAutoCreateFieldsLocked


1.4.27. TSynDictionaryInArray

TSynDictionaryInArray = ( iaFind, iaFindAndDelete, iaFindAndUpdate, iaFindAndAddIfNotExisting, iaAdd, iaAddForced );

Internal flag, used only by TSynDictionary.InArray protected method


1.4.28. TSynJsonFileSettingsClass

TSynJsonFileSettingsClass = class of TSynJsonFileSettings;

Meta-class definition of TSynJsonFileSettings


1.4.29. TSynJsonFileSettingsOption

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


1.4.30. TSynNameValueItemDynArray

TSynNameValueItemDynArray = array of TSynNameValueItem;

Name/Value pairs storage, as used by TSynNameValue class


1.5. Constants implemented in the mormot.core.json unit

1.5.1. DIC_KEY

DIC_KEY = 1;

Keys.Count integer


1.5.2. DIC_KEYCOUNT

DIC_KEYCOUNT = 0;

TSynDictionary.fSafe.Padding[DIC_*] place holders - defined here for inlining


1.5.3. DIC_TIMECOUNT

DIC_TIMECOUNT = 4;

Values.Value pointer


1.5.4. DIC_TIMESEC

DIC_TIMESEC = 5;

Timeouts.Count integer


1.5.5. DIC_TIMETIX

DIC_TIMETIX = 6;

Timeouts Seconds integer


1.5.6. DIC_VALUE

DIC_VALUE = 3;

Values.Count integer


1.5.7. DIC_VALUECOUNT

DIC_VALUECOUNT = 2;

Key.Value pointer


1.5.8. JSON_ESCAPE_ENDINGZERO

JSON_ESCAPE_ENDINGZERO = 1;

JSON_ESCAPE[] lookup value: indicates #0 (end of string)


1.5.9. JSON_ESCAPE_NONE

JSON_ESCAPE_NONE = 0;

JSON_ESCAPE[] lookup value: indicates no escape needed


1.5.10. JSON_ESCAPE_UNICODEHEX

JSON_ESCAPE_UNICODEHEX = 2;

JSON_ESCAPE[] lookup value: should be escaped as \u00xx


1.5.11. JSON_UNESCAPE_UNEXPECTED

JSON_UNESCAPE_UNEXPECTED = #0;

JSON_UNESCAPE[] lookup value: indicates #0 or unexpected control char


1.5.12. JSON_UNESCAPE_UTF16

JSON_UNESCAPE_UTF16 = #1;

JSON_UNESCAPE[] lookup value: indicates '\u0123' UTF-16 pattern


1.5.13. ROWCOUNT_PATTERN

ROWCOUNT_PATTERN: PUtf8Char = ',"rowCount":';

PatternLen = 14 chars


1.5.14. VALUES_PATTERN

VALUES_PATTERN: PUtf8Char = ',"values":[';

PatternLen = 12 chars


1.5.15. XMLUTF8_HEADER

XMLUTF8_HEADER = '<?xml version="1.0" encoding="UTF-8"?>'#13#10;

Standard header for an UTF-8 encoded XML file


1.5.16. XMLUTF8_NAMESPACE

XMLUTF8_NAMESPACE = '<contents xmlns="http://www.w3.org/2001/XMLSchema-instance">';

Standard namespace for a generic XML File


1.6. Functions or procedures implemented in the mormot.core.json unit

Functions or proceduresDescription
AutoCreateFieldsShould be called by T*AutoCreateFields constructors
AutoDestroyFieldsShould be called by T*AutoCreateFields destructors
DoRegisterAutoCreateFieldsInternal function called by AutoCreateFields() when inlined
DynArrayBlobSaveJsonSerialize a dynamic array content, supplied as raw binary buffer, as JSON
DynArrayLoadJsonFill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson with or without twoNonExpandedArrays layout
DynArrayLoadJsonFill a dynamic array content from a JSON serialization as saved by TJsonWriter.AddDynArrayJson, which won't be modified
DynArraySaveJsonSerialize a dynamic array content as JSON
ExpectPatternLen = 11 chars quickly check if an UTF-8 buffer start with the supplied Pattern
FormatJsonFast Format() function replacement, handling % but also ? parameters as JSON
FormatParamsFast Format() function replacement, handling % and ? parameters
FormatSqlFast Format() function replacement, handling % but also ? inlined parameters
FormatUtf8Rather call FormatSql() and FormatJson() functions
GetFieldCountExpandedLow-level parsing of the first expanded JSON object to guess fields count
GetFirstJsonTokenReturns the JSON type of a supplied #0 ended buffer
GetJsonFieldDecode a JSON field value in-place from an UTF-8 encoded text buffer
GetJsonFieldOrObjectOrArrayDecode a JSON content from an UTF-8 encoded buffer
GetJsonItemAsRawJsonRetrieve the next JSON item as a RawJson undecoded variable
GetJsonItemAsRawUtf8Retrieve the next JSON item as a RawUtf8 decoded buffer
GetJsonObjectOrArrayDecode a JSON object or array from an UTF-8 encoded buffer
GetJsonPropNameDecode a JSON field name in an UTF-8 encoded buffer
GetJsonPropNameShortDecode a JSON field name in an UTF-8 encoded ShortString variable
GetNextJsonTokenValidate the supplied #0 ended buffer and returns its JSON type
GetSetNameValueHelper to retrieve the bit mapped integer value of a set from its JSON text
GetSetNameValueHelper to retrieve the bit mapped integer value of a set from its JSON text
GetValueObjectGet any (potentially nested) object property by path
GotoEndJsonItemReach position just after the current JSON item in the supplied UTF-8 buffer
GotoEndJsonItemStrictReach position just after the current JSON item in the supplied UTF-8 buffer
GotoEndJsonItemStringReach position just after the current JSON string in the supplied UTF-8 buffer
GotoEndOfJsonStringGet the next character after a quoted buffer
GotoFieldCountExpandedLow-level prepare GetFieldCountExpanded() parsing returning '{' or ']'
GotoNextJsonItemReach the position of the next JSON item(s) in the supplied UTF-8 buffer
GotoNextJsonItemReach the position of the next JSON item in the supplied UTF-8 buffer
IgnoreCommaSimple method to go after the next ',' character
IsNotExpandedBufferParse JSON content in not-expanded format
IsStringTest if the supplied buffer is a "string" value or a numerical value (floating point or integer), according to the characters within
IsStringJsonTest if the supplied buffer is a "string" value or a numerical value (floating or integer), according to the JSON encoding schema
IsValidJsonTest if the supplied text seems to be a correct (extended) JSON value
IsValidJsonTest if the supplied text buffer seems to be a correct (extended) JSON value
IsValidJsonBufferTest if the supplied #0 ended buffer is a correct (extended) JSON value
JsonArrayCountCompute the number of elements of a JSON array
JsonArrayDecodeRetrieve the positions of all elements of a JSON array
JsonArrayItemGo to the #nth item of a JSON array
JsonBufferReformatFormats and indents a JSON array or document to the specified layout
JsonBufferReformatToFileFormats and indents a JSON array or document as a file
JsonBufferToXMLConvert a JSON array or document into a simple XML content
JsonDecodeDecode the supplied UTF-8 JSON object for the one supplied field name
JsonDecodeDecode the supplied UTF-8 JSON content for the supplied names
JsonDecodeDecode the supplied UTF-8 JSON content for the supplied names
JsonDecodeDecode the supplied UTF-8 JSON object for the one supplied field name
JsonDecodeDecode the supplied UTF-8 JSON object for the supplied field names
JsonDecodeDecode the supplied UTF-8 JSON object for the supplied field names
JsonDecodeDecode the supplied UTF-8 JSON object into an array of name/value pairs
JsonEncodeEncode the supplied data as an UTF-8 valid JSON object content
JsonEncodeEncode the supplied (extended) JSON content, with parameters, as an UTF-8 valid JSON object content
JsonEncodeArrayDoubleEncode the supplied floating-point array data as a valid JSON array
JsonEncodeArrayIntegerEncode the supplied integer array data as a valid JSON array
JsonEncodeArrayOfConstEncode the supplied array data as a valid JSON array content
JsonEncodeArrayOfConstEncode the supplied array data as a valid JSON array content
JsonEncodeArrayUtf8Encode the supplied RawUtf8 array data as an UTF-8 valid JSON array content
JsonEncodeNameSQLValueEncode as JSON {"name":value} object, from a potential SQL quoted value
JsonFileToObjectFill the object properties from a JSON file content
JsonObjectAsJsonArraysConvert one JSON object into two JSON arrays of keys and values
JsonObjectByPathGo to a property of a JSON object, by its full path, e.g. 'parent.child'
JsonObjectItemGo to a buffer-named property of a JSON object
JsonObjectItemGo to a named property of a JSON object
JsonObjectPropCountCompute the number of fields in a JSON object
JsonObjectsByPathReturn all matching properties of a JSON object
JsonPropNameValidReturns TRUE if the given text buffer contains simple characters as recognized by JSON extended syntax
JsonReformatFormats and indents a JSON array or document to the specified layout
JsonReformatToFileFormats and indents a JSON array or document as a file
JsonRetrieveObjectRttiCustomRetrieve a class Rtti, as saved by ObjectToJson(...,[...,woStoreClassName,...]);
JsonRetrieveStringFieldRetrieve a pointer to JSON string field content, without unescaping it
JsonSettingsToObjectParse the supplied JSON with some tolerance about Settings format
JsonToNewObjectCreate a new object instance, as saved by ObjectToJson(...,[...,woStoreClassName,...]);
JsonToObjectRead an object properties, as saved by ObjectToJson function
JsonToXMLConvert 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
JsonUnicodeEscapeToUtf8UTF-8 decode one or two \u#### JSON escaped codepoints into Dest
JsonUnicodeUnEscapeEnsure all \u#### UTF-16 JSON are decoded into plain UTF-8 content
LoadJsonUnserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson
LoadJsonInPlaceUnserialize most kind of content as JSON, using its RTTI, as saved by TJsonWriter.AddRecordJson / RecordSaveJson
NeedsJsonEscapeReturns TRUE if the given text buffers would be escaped when written as JSON
NeedsJsonEscapeReturns TRUE if the given text buffers would be escaped when written as JSON
NeedsJsonEscapeReturns TRUE if the given text buffers would be escaped when written as JSON
NotExpandedBufferRowCountPosEfficient retrieval of the number of rows in non-expanded layout
ObjArrayToJsonWrapper to serialize a T*ObjArray dynamic array as JSON
ObjectLoadJsonRead an object properties, as saved by ObjectToJson function
ObjectsToJsonWill serialize set of TObject into its UTF-8 JSON representation
ObjectToJsonFilePersist a class instance into a JSON file
ParseEndOfObjectSearch the EndOfObject of a JSON buffer, just like TGetJsonField does
PropertyFromJsonRead an TObject published property, as saved by ObjectToJson() function
QuotedStrJsonConvert UTF-8 content into a JSON string
QuotedStrJsonConvert UTF-8 buffer into a JSON string
QuotedStrJsonConvert UTF-8 content into a JSON string
RecordLoadJsonFill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson
RecordLoadJsonFill a record content from a JSON serialization as saved by TJsonWriter.AddRecordJson / RecordSaveJson
RecordSaveJsonSave record into its JSON serialization as saved by TJsonWriter.AddRecordJson
RemoveCommentsFromJsonRemove comments from a text buffer before passing it to JSON parser
RemoveCommentsFromJsonRemove comments and trailing commas from a text buffer before passing it to a JSON parser
SaveJsonSerialize most kind of content as JSON, using its RTTI
SaveJsonSerialize most kind of content as JSON, using its RTTI
SaveJsonSerialize most kind of content as JSON, using its RTTI and a type name
SaveJsonSerialize most kind of content as JSON, using its RTTI
UrlDecodeObjectDecode a specified parameter compatible with URI encoding into its original object contents
UrlEncodeJsonObjectEncode a JSON object UTF-8 buffer into URI parameters
UrlEncodeJsonObjectEncode a JSON object UTF-8 buffer into URI parameters
Utf16ToJsonUnicodeEscapeEncode one \u#### JSON escaped UTF-16 codepoint into Dest

1.6.1. AutoCreateFields

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


1.6.2. AutoDestroyFields

procedure AutoDestroyFields(ObjectInstance: TObject; Info: TRttiJson = nil);

Should be called by T*AutoCreateFields destructors
- constructor should have called AutoCreateFields()


1.6.3. DoRegisterAutoCreateFields

function DoRegisterAutoCreateFields(ObjectInstance: TObject): TRttiJson;

Internal function called by AutoCreateFields() when inlined
- do not call this internal function, but always AutoCreateFields()


1.6.4. DynArrayBlobSaveJson

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()


1.6.5. DynArrayLoadJson

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


1.6.6. DynArrayLoadJson

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

1.6.7. DynArraySaveJson

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)


1.6.8. Expect

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


1.6.9. FormatJson

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);


1.6.10. FormatParams

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


1.6.11. FormatSql

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);


1.6.12. FormatUtf8

function FormatUtf8(const Format: RawUtf8; const Args, Params: array of const; JsonFormat: boolean = false): RawUtf8; overload;

Rather call FormatSql() and FormatJson() functions


1.6.13. GetFieldCountExpanded

function GetFieldCountExpanded(P: PUtf8Char): integer;

Low-level parsing of the first expanded JSON object to guess fields count


1.6.14. GetFirstJsonToken

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


1.6.15. GetJsonField

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


1.6.16. GetJsonFieldOrObjectOrArray

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


1.6.17. GetJsonItemAsRawJson

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


1.6.18. GetJsonItemAsRawUtf8

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


1.6.19. GetJsonObjectOrArray

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


1.6.20. GetJsonPropName

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


1.6.21. GetJsonPropNameShort

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


1.6.22. GetNextJsonToken

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


1.6.23. GetSetNameValue

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


1.6.24. GetSetNameValue

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)


1.6.25. GetValueObject

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


1.6.26. GotoEndJsonItem

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


1.6.27. GotoEndJsonItemStrict

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


1.6.28. GotoEndJsonItemString

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()


1.6.29. GotoEndOfJsonString

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 "


1.6.30. GotoFieldCountExpanded

function GotoFieldCountExpanded(P: PUtf8Char): PUtf8Char;

Low-level prepare GetFieldCountExpanded() parsing returning '{' or ']'


1.6.31. GotoNextJsonItem

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


1.6.32. GotoNextJsonItem

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 ',','}',']'


1.6.33. IgnoreComma

procedure IgnoreComma(var P: PUtf8Char);

Simple method to go after the next ',' character


1.6.34. IsNotExpandedBuffer

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


1.6.35. IsString

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


1.6.36. IsStringJson

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


1.6.37. IsValidJson

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


1.6.38. IsValidJson

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


1.6.39. IsValidJsonBuffer

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


1.6.40. JsonArrayCount

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/s

1.6.41. JsonArrayDecode

function 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


1.6.42. JsonArrayItem

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


1.6.43. JsonBufferReformat

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


1.6.44. JsonBufferReformatToFile

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


1.6.45. JsonBufferToXML

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


1.6.46. JsonDecode

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


1.6.47. JsonDecode

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"


1.6.48. JsonDecode

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}'


1.6.49. JsonDecode

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


1.6.50. JsonDecode

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


1.6.51. JsonDecode

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}'


1.6.52. JsonDecode

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


1.6.53. JsonEncode

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


1.6.54. JsonEncode

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


1.6.55. JsonEncodeArrayDouble

function JsonEncodeArrayDouble( const Values: array of double): RawUtf8; overload;

Encode the supplied floating-point array data as a valid JSON array


1.6.56. JsonEncodeArrayInteger

function JsonEncodeArrayInteger( const Values: array of integer): RawUtf8; overload;

Encode the supplied integer array data as a valid JSON array


1.6.57. JsonEncodeArrayOfConst

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)


1.6.58. JsonEncodeArrayOfConst

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)


1.6.59. JsonEncodeArrayUtf8

function JsonEncodeArrayUtf8( const Values: array of RawUtf8): RawUtf8; overload;

Encode the supplied RawUtf8 array data as an UTF-8 valid JSON array content


1.6.60. JsonEncodeNameSQLValue

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()


1.6.61. JsonFileToObject

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


1.6.62. JsonObjectAsJsonArrays

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


1.6.63. JsonObjectByPath

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


1.6.64. JsonObjectItem

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


1.6.65. JsonObjectItem

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()


1.6.66. JsonObjectPropCount

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));

1.6.67. JsonObjectsByPath

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


1.6.68. JsonPropNameValid

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


1.6.69. JsonReformat

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)


1.6.70. JsonReformatToFile

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)


1.6.71. JsonRetrieveObjectRttiCustom

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


1.6.72. JsonRetrieveStringField

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


1.6.73. JsonSettingsToObject

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


1.6.74. JsonToNewObject

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


1.6.75. JsonToObject

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


1.6.76. JsonToXML

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>'


1.6.77. JsonUnicodeEscape

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


1.6.78. JsonUnicodeEscapeToUtf8

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


1.6.79. JsonUnicodeUnEscape

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


1.6.80. LoadJson

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


1.6.81. LoadJsonInPlace

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


1.6.82. NeedsJsonEscape

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


1.6.83. NeedsJsonEscape

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


1.6.84. NeedsJsonEscape

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


1.6.85. NotExpandedBufferRowCountPos

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


1.6.86. ObjArrayToJson

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()


1.6.87. ObjectLoadJson

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


1.6.88. ObjectsToJson

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


1.6.89. ObjectToJsonFile

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


1.6.90. ParseEndOfObject

function ParseEndOfObject(P: PUtf8Char; out EndOfObject: AnsiChar): PUtf8Char;

Search the EndOfObject of a JSON buffer, just like TGetJsonField does


1.6.91. PropertyFromJson

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


1.6.92. QuotedStrJson

function QuotedStrJson(const aText: RawUtf8): RawUtf8; overload;

Convert UTF-8 content into a JSON string
- with proper escaping of the content, and surounding " characters


1.6.93. QuotedStrJson

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


1.6.94. QuotedStrJson

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


1.6.95. RecordLoadJson

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


1.6.96. RecordLoadJson

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()


1.6.97. RecordSaveJson

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)


1.6.98. RemoveCommentsFromJson

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);

1.6.99. RemoveCommentsFromJson

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


1.6.100. SaveJson

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


1.6.101. SaveJson

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


1.6.102. SaveJson

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()


1.6.103. SaveJson

function SaveJson(const Value; TypeInfo: PRttiInfo): RawUtf8; overload;

Serialize most kind of content as JSON, using its RTTI


1.6.104. UrlDecodeObject

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


1.6.105. UrlEncodeJsonObject

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


1.6.106. UrlEncodeJsonObject

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


1.6.107. Utf16ToJsonUnicodeEscape

procedure Utf16ToJsonUnicodeEscape(var B: PUtf8Char; c: PtrUint; tab: PByteToWord);

Encode one \u#### JSON escaped UTF-16 codepoint into Dest


1.7. Variables implemented in the mormot.core.json unit

1.7.1. DEFAULT_WRITEOPTIONS

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


1.7.2. JSONPARSER_DEFAULTOPTIONS

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


1.7.3. JSONPARSER_DEFAULTORTOLERANTOPTIONS

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]


1.7.4. JSONPARSER_TOLERANTOPTIONS

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


1.7.5. JSON_CHARS

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 ...

1.7.6. JSON_ESCAPE

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,\,"


1.7.7. JSON_PREFETCH

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


1.7.8. JSON_TOKENS

JSON_TOKENS: TJsonTokens;

256-byte lookup table for fast branchless initial character JSON parsing


1.7.9. JSON_UNESCAPE

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


1.7.10. SERVICELOG_WRITEOPTIONS

SERVICELOG_WRITEOPTIONS: TTextWriterWriteObjectOptions = [woDontStoreDefault, woDontStoreVoid, woHideSensitivePersonalInformation];

The options used by TServiceFactoryServer.OnLogRestExecuteMethod
- you can modify this global variable to customize the whole process


1.7.11. SETTINGS_WRITEOPTIONS

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