JsonSerializerInternalReader
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerInternalReader : JsonSerializerInternalBase
{
internal enum PropertyPresence
{
None,
Null,
Value
}
private JsonSerializerProxy _internalSerializer;
public JsonSerializerInternalReader(JsonSerializer serializer)
: base(serializer)
{
}
public void Populate(JsonReader reader, object target)
{
ValidationUtils.ArgumentNotNull(target, "target");
Type type = target.GetType();
JsonContract jsonContract = Serializer._contractResolver.ResolveContract(type);
if (reader.TokenType == JsonToken.None)
reader.Read();
if (reader.TokenType == JsonToken.StartArray) {
if (jsonContract.ContractType != JsonContractType.Array)
throw JsonSerializationException.Create(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type));
JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract;
PopulateList(jsonArrayContract.ShouldCreateWrapper ? jsonArrayContract.CreateWrapper(target) : ((IList)target), reader, jsonArrayContract, null, null);
} else {
if (reader.TokenType != JsonToken.StartObject)
throw JsonSerializationException.Create(reader, "Unexpected initial token '{0}' when populating object. Expected JSON object or array.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
CheckedRead(reader);
string id = null;
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$id", StringComparison.Ordinal)) {
CheckedRead(reader);
id = ((reader.Value != null) ? reader.Value.ToString() : null);
CheckedRead(reader);
}
if (jsonContract.ContractType == JsonContractType.Dictionary) {
JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract;
PopulateDictionary(jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(target) : ((IDictionary)target), reader, jsonDictionaryContract, null, id);
} else {
if (jsonContract.ContractType != JsonContractType.Object)
throw JsonSerializationException.Create(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type));
PopulateObject(target, reader, (JsonObjectContract)jsonContract, null, id);
}
}
}
private JsonContract GetContractSafe(Type type)
{
if ((object)type == null)
return null;
return Serializer._contractResolver.ResolveContract(type);
}
public object Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
{
if (reader != null) {
JsonContract contractSafe = GetContractSafe(objectType);
try {
JsonConverter converter = GetConverter(contractSafe, null, null, null);
if (reader.TokenType == JsonToken.None && !ReadForType(reader, contractSafe, converter != null)) {
if (contractSafe != null && !contractSafe.IsNullable)
throw JsonSerializationException.Create(reader, "No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contractSafe.UnderlyingType));
return null;
}
object result = (converter == null || !converter.CanRead) ? CreateValueInternal(reader, objectType, contractSafe, null, null, null, null) : DeserializeConvertable(converter, reader, objectType, null);
if (checkAdditionalContent && reader.Read() && reader.TokenType != JsonToken.Comment)
throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
return result;
} catch (Exception ex) {
if (!IsErrorHandled(null, contractSafe, null, reader as IJsonLineInfo, reader.Path, ex)) {
ClearErrorContext();
throw;
}
HandleError(reader, false, 0);
return null;
}
}
throw new ArgumentNullException("reader");
}
private JsonSerializerProxy GetInternalSerializer()
{
if (_internalSerializer == null)
_internalSerializer = new JsonSerializerProxy(this);
return _internalSerializer;
}
private JToken CreateJToken(JsonReader reader, JsonContract contract)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
if (contract != null && (object)contract.UnderlyingType == typeof(JRaw))
return JRaw.Create(reader);
using (JTokenWriter jTokenWriter = new JTokenWriter()) {
jTokenWriter.WriteToken(reader);
return jTokenWriter.Token;
}
}
private JToken CreateJObject(JsonReader reader)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
using (JTokenWriter jTokenWriter = new JTokenWriter()) {
jTokenWriter.WriteStartObject();
if (reader.TokenType == JsonToken.PropertyName)
jTokenWriter.WriteToken(reader, reader.Depth - 1, true, true);
else
jTokenWriter.WriteEndObject();
return jTokenWriter.Token;
}
}
private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
{
if (contract != null && contract.ContractType == JsonContractType.Linq)
return CreateJToken(reader, contract);
do {
switch (reader.TokenType) {
case JsonToken.StartObject:
return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue);
case JsonToken.StartArray:
return CreateList(reader, objectType, contract, member, existingValue, null);
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.Boolean:
case JsonToken.Date:
case JsonToken.Bytes:
return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
case JsonToken.String: {
string text = (string)reader.Value;
if (string.IsNullOrEmpty(text) && (object)objectType != typeof(string) && (object)objectType != typeof(object) && contract != null && contract.IsNullable)
return null;
if ((object)objectType == typeof(byte[]))
return Convert.FromBase64String(text);
return EnsureType(reader, text, CultureInfo.InvariantCulture, contract, objectType);
}
case JsonToken.StartConstructor: {
string value = reader.Value.ToString();
return EnsureType(reader, value, CultureInfo.InvariantCulture, contract, objectType);
}
case JsonToken.Null:
case JsonToken.Undefined:
return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
case JsonToken.Raw:
return new JRaw((string)reader.Value);
default:
throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType);
case JsonToken.Comment:
break;
}
} while (reader.Read());
throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
}
internal string GetExpectedDescription(JsonContract contract)
{
switch (contract.ContractType) {
case JsonContractType.Object:
case JsonContractType.Dictionary:
case JsonContractType.Dynamic:
return "JSON object (e.g. {\"name\":\"value\"})";
case JsonContractType.Array:
return "JSON array (e.g. [1,2,3])";
case JsonContractType.Primitive:
return "JSON primitive value (e.g. string, number, boolean, null)";
case JsonContractType.String:
return "JSON string value";
default:
throw new ArgumentOutOfRangeException();
}
}
private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty)
{
JsonConverter result = null;
if (memberConverter != null)
result = memberConverter;
else if (containerProperty != null && containerProperty.ItemConverter != null) {
result = containerProperty.ItemConverter;
} else if (containerContract != null && containerContract.ItemConverter != null) {
result = containerContract.ItemConverter;
} else if (contract != null) {
JsonConverter matchingConverter;
if (contract.Converter != null)
result = contract.Converter;
else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null) {
result = matchingConverter;
} else if (contract.InternalConverter != null) {
result = contract.InternalConverter;
}
}
return result;
}
private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
{
CheckedRead(reader);
if (ReadSpecialProperties(reader, ref objectType, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out string id))
return newValue;
if (HasNoDefinedType(contract))
return CreateJObject(reader);
switch (contract.ContractType) {
case JsonContractType.Object: {
bool createdFromNonDefaultConstructor2 = false;
JsonObjectContract jsonObjectContract = (JsonObjectContract)contract;
object obj = (existingValue == null) ? CreateNewObject(reader, jsonObjectContract, member, containerMember, id, out createdFromNonDefaultConstructor2) : existingValue;
if (createdFromNonDefaultConstructor2)
return obj;
return PopulateObject(obj, reader, jsonObjectContract, member, id);
}
case JsonContractType.Primitive: {
JsonPrimitiveContract contract3 = (JsonPrimitiveContract)contract;
if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$value", StringComparison.Ordinal)) {
CheckedRead(reader);
if (reader.TokenType == JsonToken.StartObject)
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
object result = CreateValueInternal(reader, objectType, contract3, member, null, null, existingValue);
CheckedRead(reader);
return result;
}
break;
}
case JsonContractType.Dictionary: {
JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)contract;
if (existingValue != null)
return PopulateDictionary(jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(existingValue) : ((IDictionary)existingValue), reader, jsonDictionaryContract, member, id);
bool createdFromNonDefaultConstructor;
IDictionary dictionary = CreateNewDictionary(reader, jsonDictionaryContract, out createdFromNonDefaultConstructor);
if (createdFromNonDefaultConstructor) {
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 ((object)jsonDictionaryContract.ParametrizedConstructor == null)
throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
}
PopulateDictionary(dictionary, reader, jsonDictionaryContract, member, id);
if (createdFromNonDefaultConstructor) {
ConstructorInfo constructorInfo = jsonDictionaryContract.ParametrizedConstructor as ConstructorInfo;
if ((object)constructorInfo != null)
return constructorInfo.Invoke(new object[1] {
dictionary
});
return jsonDictionaryContract.ParametrizedConstructor.Invoke(null, new object[1] {
dictionary
});
}
if (dictionary is IWrappedDictionary)
return ((IWrappedDictionary)dictionary).UnderlyingDictionary;
return dictionary;
}
case JsonContractType.Dynamic: {
JsonDynamicContract contract2 = (JsonDynamicContract)contract;
return CreateDynamic(reader, contract2, member, id);
}
}
throw JsonSerializationException.Create(reader, "Cannot deserialize the current JSON object (e.g. {{\"name\":\"value\"}}) into type '{0}' because the type requires a {1} to deserialize correctly.\r\nTo 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.\r\n".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)));
}
private bool ReadSpecialProperties(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
{
id = null;
newValue = null;
if (reader.TokenType == JsonToken.PropertyName) {
string text = reader.Value.ToString();
if (text.Length > 0 && text[0] == '$') {
bool flag;
do {
text = reader.Value.ToString();
if (string.Equals(text, "$ref", StringComparison.Ordinal)) {
CheckedRead(reader);
if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null)
throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref"));
string text2 = (reader.Value != null) ? reader.Value.ToString() : null;
CheckedRead(reader);
if (text2 != null) {
if (reader.TokenType == JsonToken.PropertyName)
throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref"));
newValue = Serializer.GetReferenceResolver().ResolveReference(this, text2);
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text2, newValue.GetType())), null);
return true;
}
flag = true;
} else if (string.Equals(text, "$type", StringComparison.Ordinal)) {
CheckedRead(reader);
string text3 = reader.Value.ToString();
if ((member?.TypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? containerMember?.ItemTypeNameHandling ?? Serializer._typeNameHandling) != 0) {
ReflectionUtils.SplitFullyQualifiedTypeName(text3, out string typeName, out string assemblyName);
Type type;
try {
type = Serializer._binder.BindToType(assemblyName, typeName);
} catch (Exception ex) {
throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, text3), ex);
}
if ((object)type == null)
throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, text3));
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text3, type)), null);
if ((object)objectType != null && (object)objectType != typeof(IDynamicMetaObjectProvider) && !TypeExtensions.IsAssignableFrom(objectType, type))
throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, type.AssemblyQualifiedName, objectType.AssemblyQualifiedName));
objectType = type;
contract = GetContractSafe(type);
}
CheckedRead(reader);
flag = true;
} else if (string.Equals(text, "$id", StringComparison.Ordinal)) {
CheckedRead(reader);
id = ((reader.Value != null) ? reader.Value.ToString() : null);
CheckedRead(reader);
flag = true;
} else {
if (string.Equals(text, "$values", StringComparison.Ordinal)) {
CheckedRead(reader);
object obj = CreateList(reader, objectType, contract, member, existingValue, id);
CheckedRead(reader);
newValue = obj;
return true;
}
flag = false;
}
} while (flag && reader.TokenType == JsonToken.PropertyName);
}
}
return false;
}
private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
{
if (contract == null)
throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType));
JsonArrayContract jsonArrayContract = contract as JsonArrayContract;
if (jsonArrayContract == null)
throw JsonSerializationException.Create(reader, "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly.\r\nTo fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\n".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)));
return jsonArrayContract;
}
private void CheckedRead(JsonReader reader)
{
if (!reader.Read())
throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
}
private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id)
{
if (HasNoDefinedType(contract))
return CreateJToken(reader, contract);
JsonArrayContract jsonArrayContract = EnsureArrayContract(reader, objectType, contract);
if (existingValue != null)
return PopulateList(jsonArrayContract.ShouldCreateWrapper ? jsonArrayContract.CreateWrapper(existingValue) : ((IList)existingValue), reader, jsonArrayContract, member, id);
bool createdFromNonDefaultConstructor;
IList list = CreateNewList(reader, jsonArrayContract, out createdFromNonDefaultConstructor);
if (createdFromNonDefaultConstructor) {
if (id != null)
throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list 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 an array or readonly list, or list 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 an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if ((object)jsonArrayContract.ParametrizedConstructor == null && !jsonArrayContract.IsArray)
throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
}
if (!jsonArrayContract.IsMultidimensionalArray)
PopulateList(list, reader, jsonArrayContract, member, id);
else
PopulateMultidimensionalArray(list, reader, jsonArrayContract, member, id);
if (createdFromNonDefaultConstructor) {
if (jsonArrayContract.IsMultidimensionalArray)
list = CollectionUtils.ToMultidimensionalArray(list, jsonArrayContract.CollectionItemType, contract.CreatedType.GetArrayRank());
else {
if (!jsonArrayContract.IsArray) {
ConstructorInfo constructorInfo = jsonArrayContract.ParametrizedConstructor as ConstructorInfo;
if ((object)constructorInfo != null)
return constructorInfo.Invoke(new object[1] {
list
});
return jsonArrayContract.ParametrizedConstructor.Invoke(null, new object[1] {
list
});
}
Array array = Array.CreateInstance(jsonArrayContract.CollectionItemType, new int[1] {
list.Count
});
list.CopyTo(array, 0);
list = array;
}
} else if (list is IWrappedCollection) {
return ((IWrappedCollection)list).UnderlyingCollection;
}
return list;
}
private bool HasNoDefinedType(JsonContract contract)
{
if (contract != null && (object)contract.UnderlyingType != typeof(object) && contract.ContractType != JsonContractType.Linq)
return (object)contract.UnderlyingType == typeof(IDynamicMetaObjectProvider);
return true;
}
private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType)
{
if ((object)targetType == null)
return value;
Type objectType = ReflectionUtils.GetObjectType(value);
if ((object)objectType != targetType) {
if (value != null || !contract.IsNullable)
try {
if (!contract.IsConvertable)
return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType);
JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract;
if (contract.IsEnum) {
if (value is string)
return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true);
if (ConvertUtils.IsInteger(jsonPrimitiveContract.TypeCode))
return Enum.ToObject(contract.NonNullableUnderlyingType, value);
}
if (!(value is BigInteger))
return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
return ConvertUtils.FromBigInteger((BigInteger)value, targetType);
} catch (Exception ex) {
throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(value), targetType), ex);
}
return null;
}
return value;
}
private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target)
{
if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue))
return false;
object obj;
if (propertyConverter != null && propertyConverter.CanRead) {
if (!gottenCurrentValue && target != null && property.Readable)
currentValue = property.ValueProvider.GetValue(target);
obj = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue);
} else
obj = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, useExistingValue ? currentValue : null);
if ((!useExistingValue || obj != currentValue) && ShouldSetPropertyValue(property, obj)) {
property.ValueProvider.SetValue(target, obj);
if (property.SetIsSpecified != null) {
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null);
property.SetIsSpecified(target, true);
}
return true;
}
return useExistingValue;
}
private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue)
{
currentValue = null;
useExistingValue = false;
propertyContract = null;
gottenCurrentValue = false;
if (property.Ignored)
return true;
JsonToken tokenType = reader.TokenType;
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
ObjectCreationHandling valueOrDefault = property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling);
if (valueOrDefault != ObjectCreationHandling.Replace && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject) && property.Readable) {
currentValue = property.ValueProvider.GetValue(target);
gottenCurrentValue = true;
if (currentValue != null) {
propertyContract = GetContractSafe(currentValue.GetType());
useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
}
}
if (!property.Writable && !useExistingValue)
return true;
if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && tokenType == JsonToken.Null)
return true;
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && JsonReader.IsPrimitiveToken(tokenType) && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue()))
return true;
if (currentValue == null)
propertyContract = property.PropertyContract;
else {
propertyContract = GetContractSafe(currentValue.GetType());
if (propertyContract != property.PropertyContract)
propertyConverter = GetConverter(propertyContract, property.MemberConverter, containerContract, containerProperty);
}
return false;
}
private void AddReference(JsonReader reader, string id, object value)
{
try {
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Read object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, id, value.GetType())), null);
Serializer.GetReferenceResolver().AddReference(this, id, value);
} catch (Exception ex) {
throw JsonSerializationException.Create(reader, "Error reading object reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, id), ex);
}
}
private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
{
return (value & flag) == flag;
}
private bool ShouldSetPropertyValue(JsonProperty property, object value)
{
if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && value == null)
return false;
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue()))
return false;
if (!property.Writable)
return false;
return true;
}
private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultConstructor)
{
if (!contract.CanDeserialize)
throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType));
if (contract.IsReadOnlyOrFixedSize) {
createdFromNonDefaultConstructor = true;
IList list = contract.CreateTemporaryCollection();
if (contract.ShouldCreateWrapper)
list = contract.CreateWrapper(list);
return list;
}
if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) {
object obj = contract.DefaultCreator();
if (contract.ShouldCreateWrapper)
obj = contract.CreateWrapper(obj);
createdFromNonDefaultConstructor = false;
return (IList)obj;
}
if ((object)contract.ParametrizedConstructor != null) {
createdFromNonDefaultConstructor = true;
return contract.CreateTemporaryCollection();
}
throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
}
private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultConstructor)
{
if (contract.IsReadOnlyOrFixedSize) {
createdFromNonDefaultConstructor = true;
return contract.CreateTemporaryDictionary();
}
if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) {
object obj = contract.DefaultCreator();
if (contract.ShouldCreateWrapper)
obj = contract.CreateWrapper(obj);
createdFromNonDefaultConstructor = false;
return (IDictionary)obj;
}
if ((object)contract.ParametrizedConstructor != null) {
createdFromNonDefaultConstructor = true;
return contract.CreateTemporaryDictionary();
}
throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
}
private void OnDeserializing(JsonReader reader, JsonContract contract, object value)
{
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
contract.InvokeOnDeserializing(value, Serializer._context);
}
private void OnDeserialized(JsonReader reader, JsonContract contract, object value)
{
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
contract.InvokeOnDeserialized(value, Serializer._context);
}
private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, string id)
{
IWrappedDictionary wrappedDictionary = dictionary as IWrappedDictionary;
object obj = (wrappedDictionary != null) ? wrappedDictionary.UnderlyingDictionary : dictionary;
if (id != null)
AddReference(reader, id, obj);
OnDeserializing(reader, contract, obj);
int depth = reader.Depth;
if (contract.KeyContract == null)
contract.KeyContract = GetContractSafe(contract.DictionaryKeyType);
if (contract.ItemContract == null)
contract.ItemContract = GetContractSafe(contract.DictionaryValueType);
JsonConverter jsonConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty);
PrimitiveTypeCode primitiveTypeCode = (contract.KeyContract is JsonPrimitiveContract) ? ((JsonPrimitiveContract)contract.KeyContract).TypeCode : PrimitiveTypeCode.Empty;
bool flag = false;
do {
switch (reader.TokenType) {
case JsonToken.PropertyName: {
object obj2 = reader.Value;
try {
try {
obj2 = (((primitiveTypeCode == PrimitiveTypeCode.DateTime || primitiveTypeCode == PrimitiveTypeCode.DateTimeNullable) && DateTimeUtils.TryParseDateTime(obj2.ToString(), DateParseHandling.DateTime, reader.DateTimeZoneHandling, out object dt)) ? dt : (((primitiveTypeCode != PrimitiveTypeCode.DateTimeOffset && primitiveTypeCode != PrimitiveTypeCode.DateTimeOffsetNullable) || !DateTimeUtils.TryParseDateTime(obj2.ToString(), DateParseHandling.DateTimeOffset, reader.DateTimeZoneHandling, out dt)) ? EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType) : dt));
} catch (Exception ex) {
throw JsonSerializationException.Create(reader, "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex);
}
if (!ReadForType(reader, contract.ItemContract, jsonConverter != null))
throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
object obj4 = dictionary[obj2] = ((jsonConverter == null || !jsonConverter.CanRead) ? CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(jsonConverter, reader, contract.DictionaryValueType, null));
} catch (Exception ex2) {
if (!IsErrorHandled(obj, contract, obj2, reader as IJsonLineInfo, reader.Path, ex2))
throw;
HandleError(reader, true, depth);
}
break;
}
case JsonToken.EndObject:
flag = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
case JsonToken.Comment:
break;
}
} while (!flag && reader.Read());
if (!flag)
ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing object.");
OnDeserialized(reader, contract, obj);
return obj;
}
private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
{
int arrayRank = contract.UnderlyingType.GetArrayRank();
if (id != null)
AddReference(reader, id, list);
OnDeserializing(reader, contract, list);
JsonContract contractSafe = GetContractSafe(contract.CollectionItemType);
JsonConverter converter = GetConverter(contractSafe, null, contract, containerProperty);
int? nullable = null;
Stack<IList> stack = new Stack<IList>();
stack.Push(list);
IList list2 = list;
bool flag = false;
do {
int depth = reader.Depth;
if (stack.Count == arrayRank) {
try {
if (ReadForType(reader, contractSafe, converter != null)) {
switch (reader.TokenType) {
case JsonToken.EndArray:
stack.Pop();
list2 = stack.Peek();
nullable = null;
break;
default: {
object value = (converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contractSafe, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null);
list2.Add(value);
break;
}
case JsonToken.Comment:
break;
}
continue;
}
} catch (Exception ex) {
JsonPosition position = reader.GetPosition(depth);
if (!IsErrorHandled(list, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, true, depth);
if (nullable.HasValue && nullable == position.Position)
throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
nullable = position.Position;
continue;
}
break;
}
if (!reader.Read())
break;
switch (reader.TokenType) {
case JsonToken.StartArray: {
IList list3 = new List<object>();
list2.Add(list3);
stack.Push(list3);
list2 = list3;
break;
}
case JsonToken.EndArray:
stack.Pop();
if (stack.Count > 0)
list2 = stack.Peek();
else
flag = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing multidimensional array: " + reader.TokenType);
case JsonToken.Comment:
break;
}
} while (!flag);
if (!flag)
ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array.");
OnDeserialized(reader, contract, list);
return list;
}
private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object currentObject, string message)
{
try {
throw JsonSerializationException.Create(reader, message);
} catch (Exception ex) {
if (!IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, false, 0);
}
}
private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
{
IWrappedCollection wrappedCollection = list as IWrappedCollection;
object obj = (wrappedCollection != null) ? wrappedCollection.UnderlyingCollection : list;
if (id != null)
AddReference(reader, id, obj);
if (list.IsFixedSize) {
reader.Skip();
return obj;
}
OnDeserializing(reader, contract, obj);
int depth = reader.Depth;
if (contract.ItemContract == null)
contract.ItemContract = GetContractSafe(contract.CollectionItemType);
JsonConverter converter = GetConverter(contract.ItemContract, null, contract, containerProperty);
int? nullable = null;
bool flag = false;
do {
try {
if (ReadForType(reader, contract.ItemContract, converter != null)) {
switch (reader.TokenType) {
case JsonToken.EndArray:
flag = true;
break;
default: {
object value = (converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null);
list.Add(value);
break;
}
case JsonToken.Comment:
break;
}
continue;
}
} catch (Exception ex) {
JsonPosition position = reader.GetPosition(depth);
if (!IsErrorHandled(obj, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, true, depth);
if (nullable.HasValue && nullable == position.Position)
throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
nullable = position.Position;
continue;
}
break;
} while (!flag);
if (!flag)
ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing array.");
OnDeserialized(reader, contract, obj);
return obj;
}
private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, string id)
{
if (!contract.IsInstantiable)
throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
if (contract.DefaultCreator == null || (contract.DefaultCreatorNonPublic && Serializer._constructorHandling != ConstructorHandling.AllowNonPublicDefaultConstructor))
throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
IDynamicMetaObjectProvider dynamicMetaObjectProvider = (IDynamicMetaObjectProvider)contract.DefaultCreator();
if (id != null)
AddReference(reader, id, dynamicMetaObjectProvider);
OnDeserializing(reader, contract, dynamicMetaObjectProvider);
int depth = reader.Depth;
bool flag = false;
do {
switch (reader.TokenType) {
case JsonToken.PropertyName: {
string text = reader.Value.ToString();
try {
if (!reader.Read())
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text));
JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text);
if (closestMatchProperty != null && closestMatchProperty.Writable && !closestMatchProperty.Ignored) {
if (closestMatchProperty.PropertyContract == null)
closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType);
JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.MemberConverter, null, null);
if (!SetPropertyValue(closestMatchProperty, converter, null, member, reader, dynamicMetaObjectProvider))
reader.Skip();
} else {
Type type = JsonReader.IsPrimitiveToken(reader.TokenType) ? reader.ValueType : typeof(IDynamicMetaObjectProvider);
JsonContract contractSafe = GetContractSafe(type);
JsonConverter converter2 = GetConverter(contractSafe, null, null, member);
object value = (converter2 == null || !converter2.CanRead) ? CreateValueInternal(reader, type, contractSafe, null, null, member, null) : DeserializeConvertable(converter2, reader, type, null);
contract.TrySetMember(dynamicMetaObjectProvider, text, value);
}
} catch (Exception ex) {
if (!IsErrorHandled(dynamicMetaObjectProvider, contract, text, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, true, depth);
}
break;
}
case JsonToken.EndObject:
flag = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
}
} while (!flag && reader.Read());
if (!flag)
ThrowUnexpectedEndException(reader, contract, dynamicMetaObjectProvider, "Unexpected end when deserializing object.");
OnDeserialized(reader, contract, dynamicMetaObjectProvider);
return dynamicMetaObjectProvider;
}
private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
{
ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
Dictionary<JsonProperty, PropertyPresence> dictionary = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary((JsonProperty m) => m, (JsonProperty m) => PropertyPresence.None) : null;
Type underlyingType = contract.UnderlyingType;
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);
IDictionary<string, object> extensionData;
IDictionary<JsonProperty, object> dictionary2 = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, underlyingType, out extensionData);
IDictionary<ParameterInfo, object> dictionary3 = ((IEnumerable<ParameterInfo>)constructorInfo.GetParameters()).ToDictionary((Func<ParameterInfo, ParameterInfo>)((ParameterInfo p) => p), (Func<ParameterInfo, object>)((ParameterInfo p) => null));
IDictionary<JsonProperty, object> dictionary4 = new Dictionary<JsonProperty, object>();
foreach (KeyValuePair<JsonProperty, object> item in dictionary2) {
IDictionary<ParameterInfo, object> source = dictionary3;
Func<KeyValuePair<ParameterInfo, object>, string> valueSelector = (KeyValuePair<ParameterInfo, object> kv) => kv.Key.Name;
KeyValuePair<JsonProperty, object> keyValuePair = item;
ParameterInfo key = source.ForgivingCaseSensitiveFind(valueSelector, keyValuePair.Key.UnderlyingName).Key;
if (key != null) {
IDictionary<ParameterInfo, object> dictionary5 = dictionary3;
ParameterInfo key2 = key;
KeyValuePair<JsonProperty, object> keyValuePair2 = item;
dictionary5[key2] = keyValuePair2.Value;
} else
dictionary4.Add(item);
if (dictionary != null) {
JsonProperty jsonProperty = dictionary.Keys.FirstOrDefault(delegate(JsonProperty p) {
string propertyName = p.PropertyName;
KeyValuePair<JsonProperty, object> keyValuePair4 = item;
return propertyName == keyValuePair4.Key.PropertyName;
});
if (jsonProperty != null) {
Dictionary<JsonProperty, PropertyPresence> dictionary6 = dictionary;
JsonProperty key3 = jsonProperty;
KeyValuePair<JsonProperty, object> keyValuePair3 = item;
dictionary6[key3] = ((keyValuePair3.Value == null) ? PropertyPresence.Null : PropertyPresence.Value);
}
}
}
object obj = constructorInfo.Invoke(dictionary3.Values.ToArray());
if (id != null)
AddReference(reader, id, obj);
OnDeserializing(reader, contract, obj);
foreach (KeyValuePair<JsonProperty, object> item2 in dictionary4) {
JsonProperty key4 = item2.Key;
object value = item2.Value;
if (ShouldSetPropertyValue(key4, value))
key4.ValueProvider.SetValue(obj, value);
else if (!key4.Writable && value != null) {
JsonContract jsonContract = Serializer._contractResolver.ResolveContract(key4.PropertyType);
if (jsonContract.ContractType == JsonContractType.Array) {
JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract;
object value2 = key4.ValueProvider.GetValue(obj);
if (value2 != null) {
IWrappedCollection wrappedCollection = jsonArrayContract.CreateWrapper(value2);
IWrappedCollection wrappedCollection2 = jsonArrayContract.CreateWrapper(value);
foreach (object item3 in wrappedCollection2) {
wrappedCollection.Add(item3);
}
}
} else if (jsonContract.ContractType == JsonContractType.Dictionary) {
JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract;
object value3 = key4.ValueProvider.GetValue(obj);
if (value3 != null) {
IDictionary dictionary7 = jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(value3) : ((IDictionary)value3);
IDictionary dictionary8 = jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(value) : ((IDictionary)value);
IDictionaryEnumerator enumerator4 = dictionary8.GetEnumerator();
try {
while (enumerator4.MoveNext()) {
DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator4.Current;
dictionary7.Add(dictionaryEntry.Key, dictionaryEntry.Value);
}
} finally {
(enumerator4 as IDisposable)?.Dispose();
}
}
}
}
}
if (extensionData != null) {
foreach (KeyValuePair<string, object> item4 in extensionData) {
contract.ExtensionDataSetter(obj, item4.Key, item4.Value);
}
}
EndObject(obj, reader, contract, reader.Depth, dictionary);
OnDeserialized(reader, contract, obj);
return obj;
}
private object DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue)
{
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null);
object result = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer());
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null);
return result;
}
private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType, out IDictionary<string, object> extensionData)
{
extensionData = ((contract.ExtensionDataSetter != null) ? new Dictionary<string, object>() : null);
IDictionary<JsonProperty, object> dictionary = new Dictionary<JsonProperty, object>();
bool flag = false;
do {
switch (reader.TokenType) {
case JsonToken.PropertyName: {
string text = reader.Value.ToString();
JsonProperty jsonProperty = contract.ConstructorParameters.GetClosestMatchProperty(text) ?? contract.Properties.GetClosestMatchProperty(text);
if (jsonProperty != null) {
if (jsonProperty.PropertyContract == null)
jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType);
JsonConverter converter = GetConverter(jsonProperty.PropertyContract, jsonProperty.MemberConverter, contract, containerProperty);
if (!ReadForType(reader, jsonProperty.PropertyContract, converter != null))
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text));
if (!jsonProperty.Ignored) {
if (jsonProperty.PropertyContract == null)
jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType);
object obj2 = dictionary[jsonProperty] = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, jsonProperty.PropertyType, jsonProperty.PropertyContract, jsonProperty, contract, containerProperty, null) : DeserializeConvertable(converter, reader, jsonProperty.PropertyType, null));
break;
}
} else {
if (!reader.Read())
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text));
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null);
if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, objectType.get_Name()));
}
if (extensionData != null) {
object value = CreateValueInternal(reader, null, null, null, contract, containerProperty, null);
extensionData[text] = value;
} else
reader.Skip();
break;
}
case JsonToken.EndObject:
flag = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
case JsonToken.Comment:
break;
}
} while (!flag && reader.Read());
return dictionary;
}
private bool ReadForType(JsonReader reader, JsonContract contract, bool hasConverter)
{
if (hasConverter)
return reader.Read();
switch (contract?.InternalReadType ?? ReadType.Read) {
case ReadType.Read:
do {
if (!reader.Read())
return false;
} while (reader.TokenType == JsonToken.Comment);
return true;
case ReadType.ReadAsInt32:
reader.ReadAsInt32();
break;
case ReadType.ReadAsDecimal:
reader.ReadAsDecimal();
break;
case ReadType.ReadAsBytes:
reader.ReadAsBytes();
break;
case ReadType.ReadAsString:
reader.ReadAsString();
break;
case ReadType.ReadAsDateTime:
reader.ReadAsDateTime();
break;
case ReadType.ReadAsDateTimeOffset:
reader.ReadAsDateTimeOffset();
break;
default:
throw new ArgumentOutOfRangeException();
}
return reader.TokenType != JsonToken.None;
}
public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultConstructor)
{
object obj = null;
if (!objectContract.IsInstantiable)
throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));
if ((object)objectContract.OverrideConstructor != null) {
if (objectContract.OverrideConstructor.GetParameters().Length > 0) {
createdFromNonDefaultConstructor = true;
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.OverrideConstructor, id);
}
obj = objectContract.OverrideConstructor.Invoke(null);
} else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || (object)objectContract.ParametrizedConstructor == null)) {
obj = objectContract.DefaultCreator();
} else if ((object)objectContract.ParametrizedConstructor != null) {
createdFromNonDefaultConstructor = true;
return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedConstructor, id);
}
if (obj == null)
throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));
createdFromNonDefaultConstructor = false;
return obj;
}
private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id)
{
OnDeserializing(reader, contract, newObject);
Dictionary<JsonProperty, PropertyPresence> dictionary = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary((JsonProperty m) => m, (JsonProperty m) => PropertyPresence.None) : null;
if (id != null)
AddReference(reader, id, newObject);
int depth = reader.Depth;
bool flag = false;
do {
switch (reader.TokenType) {
case JsonToken.PropertyName: {
string text = reader.Value.ToString();
try {
JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text);
if (closestMatchProperty == null) {
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null);
if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType.get_Name()));
if (reader.Read())
SetExtensionData(contract, member, reader, text, newObject);
} else {
if (closestMatchProperty.PropertyContract == null)
closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType);
JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.MemberConverter, contract, member);
if (!ReadForType(reader, closestMatchProperty.PropertyContract, converter != null))
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text));
SetPropertyPresence(reader, closestMatchProperty, dictionary);
if (!SetPropertyValue(closestMatchProperty, converter, contract, member, reader, newObject))
SetExtensionData(contract, member, reader, text, newObject);
}
} catch (Exception ex) {
if (!IsErrorHandled(newObject, contract, text, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, true, depth);
}
break;
}
case JsonToken.EndObject:
flag = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
case JsonToken.Comment:
break;
}
} while (!flag && reader.Read());
if (!flag)
ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");
EndObject(newObject, reader, contract, depth, dictionary);
OnDeserialized(reader, contract, newObject);
return newObject;
}
private void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o)
{
if (contract.ExtensionDataSetter != null)
try {
object value = CreateValueInternal(reader, null, null, null, contract, member, null);
contract.ExtensionDataSetter(o, memberName, value);
} catch (Exception ex) {
throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex);
}
else
reader.Skip();
}
private void EndObject(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
{
if (propertiesPresence != null) {
foreach (KeyValuePair<JsonProperty, PropertyPresence> item in propertiesPresence) {
JsonProperty key = item.Key;
PropertyPresence value = item.Value;
if (value == PropertyPresence.None || value == PropertyPresence.Null)
try {
Required required = key._required ?? contract.ItemRequired ?? Required.Default;
switch (value) {
case PropertyPresence.None:
if (required == Required.AllowNull || required == Required.Always)
throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, key.PropertyName));
if (key.PropertyContract == null)
key.PropertyContract = GetContractSafe(key.PropertyType);
if (HasFlag(key.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && key.Writable)
key.ValueProvider.SetValue(newObject, EnsureType(reader, key.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, key.PropertyContract, key.PropertyType));
break;
case PropertyPresence.Null:
if (required == Required.Always)
throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, key.PropertyName));
break;
}
} catch (Exception ex) {
if (!IsErrorHandled(newObject, contract, key.PropertyName, reader as IJsonLineInfo, reader.Path, ex))
throw;
HandleError(reader, true, initialDepth);
}
}
}
}
private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary<JsonProperty, PropertyPresence> requiredProperties)
{
if (property != null && requiredProperties != null)
requiredProperties[property] = ((reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined) ? PropertyPresence.Null : PropertyPresence.Value);
}
private void HandleError(JsonReader reader, bool readPastError, int initialDepth)
{
ClearErrorContext();
if (readPastError) {
reader.Skip();
while (reader.Depth > initialDepth + 1 && reader.Read()) {
}
}
}
}
}