We define the following as an array with metadata:
{
"$id": "1",
"$values": []
}
Which represents a serialized enumerable with ReferenceHandling.Preserve, as shown in the next code.
JsonSerializerOptions opts = new JsonSerializerOptions
{
ReferenceHandling = ReferenceHandling.Preserve
};
List<int> arr = new List<int>();
JsonSerializer.Serialize(arr, opts);
The current implementation for this case relies on pushing a ReadStackFrame on properties OR replacing the existing one on elements, it uses the internal type JsonPreservedReference<T>, where T is the original type of the JSON array.
Although is very convenient (at least for me) to treat the array with metadata as an object that contains a Values property, a push/replacement is not very optimal since doing this involves doing an extra allocation for the "dummy" object that is also added to the cache of types in JsonSerializerOptions and the T gets added to the JsonClassInfo.PropertyCache.
As an alternative, we may use dummy properties to avoid the allocations, or at the very least try to switch the JsonPreservedReference from a class to a struct.
cc @ahsonkhan, @steveharter, @layomia