in src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs [374:535]
private object? CreateObject(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member,
JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue
)
{
string? id;
var resolvedObjectType = objectType;
if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore)
{
// don't look for metadata properties
reader.ReadAndAssert();
id = null;
}
else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead)
{
if (!(reader is JTokenReader tokenReader))
{
var t = JToken.ReadFrom(reader);
tokenReader = (JTokenReader)t.CreateReader();
tokenReader.Culture = reader.Culture;
tokenReader.DateFormatString = reader.DateFormatString;
tokenReader.DateParseHandling = reader.DateParseHandling;
tokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
tokenReader.FloatParseHandling = reader.FloatParseHandling;
tokenReader.SupportMultipleContent = reader.SupportMultipleContent;
// start
tokenReader.ReadAndAssert();
reader = tokenReader;
}
if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember,
existingValue, out var newValue, out id)) return newValue;
}
else
{
reader.ReadAndAssert();
if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue,
out var newValue, out id)) return newValue;
}
if (HasNoDefinedType(contract)) return CreateJObject(reader);
MiscellaneousUtils.Assert(resolvedObjectType != null);
MiscellaneousUtils.Assert(contract != null);
switch (contract.ContractType)
{
case JsonContractType.Object:
{
var createdFromNonDefaultCreator = false;
var objectContract = (JsonObjectContract)contract;
object targetObject;
// check that if type name handling is being used that the existing value is compatible with the specified type
if (existingValue != null && (resolvedObjectType == objectType || resolvedObjectType.IsAssignableFrom(existingValue.GetType())))
targetObject = existingValue;
else
targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultCreator);
// don't populate if read from non-default creator because the object has already been read
if (createdFromNonDefaultCreator) return targetObject;
return PopulateObject(targetObject, reader, objectContract, member, id);
}
case JsonContractType.Primitive:
{
var primitiveContract = (JsonPrimitiveContract)contract;
// if the content is inside $value then read past it
if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore
&& reader.TokenType == JsonToken.PropertyName
&& string.Equals(reader.Value!.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
{
reader.ReadAndAssert();
// the token should not be an object because the $type value could have been included in the object
// without needing the $value property
if (reader.TokenType == JsonToken.StartObject)
throw JsonSerializationException.Create(reader,
"Unexpected token when deserializing primitive value: " + reader.TokenType);
var value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue);
reader.ReadAndAssert();
return value;
}
break;
}
case JsonContractType.Dictionary:
{
var dictionaryContract = (JsonDictionaryContract)contract;
object targetDictionary;
if (existingValue == null)
{
var dictionary = CreateNewDictionary(reader, dictionaryContract, out var createdFromNonDefaultCreator);
if (createdFromNonDefaultCreator)
{
if (id != null)
throw JsonSerializationException.Create(reader,
"Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}."
.FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.OnSerializingCallbacks.Count > 0)
throw JsonSerializationException.Create(reader,
"Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}."
.FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.OnErrorCallbacks.Count > 0)
throw JsonSerializationException.Create(reader,
"Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(
CultureInfo.InvariantCulture, contract.UnderlyingType));
if (!dictionaryContract.HasParameterizedCreatorInternal)
throw JsonSerializationException.Create(reader,
"Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture,
contract.UnderlyingType));
}
PopulateDictionary(dictionary, reader, dictionaryContract, member, id);
if (createdFromNonDefaultCreator)
{
var creator = (dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator)!;
return creator(dictionary);
}
if (dictionary is IWrappedDictionary wrappedDictionary) return wrappedDictionary.UnderlyingDictionary;
targetDictionary = dictionary;
}
else
targetDictionary =
PopulateDictionary(
dictionaryContract.ShouldCreateWrapper || !(existingValue is IDictionary)
? dictionaryContract.CreateWrapper(existingValue)
: (IDictionary)existingValue, reader, dictionaryContract, member, id);
return targetDictionary;
}
#if HAVE_DYNAMIC
case JsonContractType.Dynamic:
JsonDynamicContract dynamicContract = (JsonDynamicContract)contract;
return CreateDynamic(reader, dynamicContract, member, id);
#endif
#if HAVE_BINARY_SERIALIZATION
case JsonContractType.Serializable:
JsonISerializableContract serializableContract = (JsonISerializableContract)contract;
return CreateISerializable(reader, serializableContract, member, id);
#endif
}
var message =
@"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly."
+ Environment.NewLine +
@"To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object."
+ Environment.NewLine;
message = message.FormatWith(CultureInfo.InvariantCulture, resolvedObjectType, GetExpectedDescription(contract));
throw JsonSerializationException.Create(reader, message);
}