This procedure maps the fields of a TJSONObject
to the corresponding properties of a Delphi object (TObject
). It uses RTTI (Run-Time Type Information) to dynamically access object properties and assign values from the JSON, supporting both simple types (like integers, strings, and dates) and complex types (like dynamic arrays).
AObject: TObject
: The object instance to which the JSON data will be mapped.AJSON: TJSONObject
: The JSON object containing the data that will populateAObject
.
-
RTTI Context Initialization
Context := TRttiContext.Create;
- The
TRttiContext
is created to access metadata about the object at runtime. It enables us to retrieve information about the object's properties and methods.
- The
-
Iterating Through JSON Pairs
for JsonPair in AJSON do
- This loop iterates over each key-value pair in the provided
TJSONObject
. EachJsonPair
consists of a key (JsonString
) and a value (JsonValue
).
- This loop iterates over each key-value pair in the provided
-
Get Object Property
Prop := RttiType.GetProperty(JsonPair.JsonString.Value);
- For each JSON key, the corresponding property of the object (
AObject
) is retrieved using RTTI.RttiType
represents the class type of the object, andGetProperty
looks for a matching property name.
- For each JSON key, the corresponding property of the object (
-
Handling Dynamic Arrays
if (Prop.PropertyType.TypeKind = tkDynArray) and (JsonPair.JsonValue is TJSONArray) then
-
If the property is a dynamic array and the JSON value is a JSON array (
TJSONArray
), the procedure proceeds with handling arrays. -
Array Handling:
-
Initialize the Array:
SetLength(TValueArray, JsonArray.Count);
The procedure creates an array (
TValueArray
) ofTValue
with the same size as the JSON array. -
Determine Array Element Class:
ElemClass := (Prop.PropertyType as TRttiDynamicArrayType).ElementType.AsInstance.MetaclassType;
RTTI is used to retrieve the class of the elements in the dynamic array. This allows the procedure to dynamically create objects for each array element.
-
Populate Array:
SubObject := ElemClass.Create; JSONToObject(SubObject, JsonArray.Items[I] as TJSONObject); TValueArray[I] := TValue.From(SubObject);
For each item in the JSON array:
- A new instance of the element class (
SubObject
) is created. - The procedure recursively calls
JSONToObject
to populate the nested object with JSON data. - The object is then added to
TValueArray
as aTValue
.
- A new instance of the element class (
-
Assign Array to Object Property:
ArrayValue := TValue.FromArray(Prop.PropertyType.Handle, TValueArray); Prop.SetValue(AObject, ArrayValue);
The dynamic array is converted to
TValue
and assigned to the property of the object (AObject
).
-
-
-
Handling Simple Types (Strings, Numbers, Booleans)
-
If the property is not an array, the procedure handles simple data types like strings, integers, booleans, and dates.
-
Null Values:
if JsonPair.JsonValue.Null then Prop.SetValue(AObject, TValue.Empty);
If the JSON value is null, the property is set to an empty value.
-
Numbers:
if Prop.PropertyType.Handle = TypeInfo(integer) then Prop.SetValue(AObject, TValue.From<integer>(TJSONNumber(JsonPair.JsonValue).AsInt))
If the property is of type
integer
ordouble
, the JSON number is converted and assigned. -
Booleans:
if JsonPair.JsonValue is TJSONTrue then Prop.SetValue(AObject, TValue.From<Boolean>(True))
JSON
true
andfalse
values are assigned as booleans. -
Strings:
if JsonPair.JsonValue is TJSONString then Prop.SetValue(AObject, TValue.From<string>(TJSONString(JsonPair.JsonValue).Value))
If the value is a string, it is directly assigned to the property.
-
Dates:
if Prop.PropertyType.Handle = TypeInfo(TDate) then Prop.SetValue(AObject, TValue.From<TDate>(ISO8601ToDate(TJSONString(JsonPair.JsonValue).Value, False)))
Strings that represent dates are converted to
TDate
orTDateTime
using theISO8601ToDate
function and assigned.
-
-
Unsupported Types Handling
- If the JSON value does not match a supported type, an exception is raised:
raise Exception.CreateFmt('Tipo de JSON não suportado para a propriedade "%s".', [Prop.Name]);
- If the JSON value does not match a supported type, an exception is raised:
-
RTTI Context Cleanup
finally Context.Free; end;
- The RTTI context is freed to release memory resources once the procedure completes.
- Recursion: The function is recursive for nested JSON objects, making it capable of handling complex data structures.
- Array Handling: Dynamic arrays require special handling due to their complex nature. Ensure that
ElemClass
is correctly identified for all array elements. - Exception Handling: The procedure includes exception handling to manage invalid JSON structures and unexpected property types.
- Supported Types: The current version supports integers, doubles, booleans, strings, dates, and dynamic arrays. If you need to support additional types, extend the type-checking logic in the appropriate sections.
- RTTI Performance: While RTTI is powerful, it may introduce performance overhead in large datasets. Consider optimizing if necessary.
By following this documentation, future modifications should be easier, as each section clearly explains its purpose and behavior.