<PackageReference Include="Newtonsoft.Json" Version="6.0.8" />

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; 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 (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && 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) { if ((object)contract.UnderlyingType == typeof(JRaw)) return JRaw.Create(reader); if (reader.TokenType == JsonToken.Null && (object)contract.UnderlyingType != typeof(JValue) && (object)contract.UnderlyingType != typeof(JToken)) return null; } 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(); do { if (reader.TokenType == JsonToken.PropertyName) { string text = (string)reader.Value; while (reader.Read() && reader.TokenType == JsonToken.Comment) { } if (!CheckPropertyName(reader, text)) { jTokenWriter.WritePropertyName(text); jTokenWriter.WriteToken(reader, true, true); } } else if (reader.TokenType != JsonToken.Comment) { jTokenWriter.WriteEndObject(); return jTokenWriter.Token; } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } } 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) { Type objectType2 = objectType; string id; if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore) { CheckedRead(reader); id = null; } else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { JTokenReader jTokenReader = reader as JTokenReader; if (jTokenReader == null) { JToken jToken = JToken.ReadFrom(reader); jTokenReader = (JTokenReader)jToken.CreateReader(); jTokenReader.Culture = reader.Culture; jTokenReader.DateFormatString = reader.DateFormatString; jTokenReader.DateParseHandling = reader.DateParseHandling; jTokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; jTokenReader.FloatParseHandling = reader.FloatParseHandling; jTokenReader.SupportMultipleContent = reader.SupportMultipleContent; CheckedRead(jTokenReader); reader = jTokenReader; } if (ReadMetadataPropertiesToken(jTokenReader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out id)) return newValue; } else { CheckedRead(reader); if (ReadMetadataProperties(reader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue2, out id)) return newValue2; } if (HasNoDefinedType(contract)) return CreateJObject(reader); switch (contract.ContractType) { case JsonContractType.Object: { bool createdFromNonDefaultCreator2 = false; JsonObjectContract jsonObjectContract = (JsonObjectContract)contract; object obj = (existingValue == null || ((object)objectType2 != objectType && !TypeExtensions.IsAssignableFrom(objectType2, existingValue.GetType()))) ? CreateNewObject(reader, jsonObjectContract, member, containerMember, id, out createdFromNonDefaultCreator2) : existingValue; if (createdFromNonDefaultCreator2) return obj; return PopulateObject(obj, reader, jsonObjectContract, member, id); } case JsonContractType.Primitive: { JsonPrimitiveContract contract3 = (JsonPrimitiveContract)contract; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && 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, objectType2, 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 createdFromNonDefaultCreator; IDictionary dictionary = CreateNewDictionary(reader, jsonDictionaryContract, out 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 (!jsonDictionaryContract.HasParametrizedCreator) throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } PopulateDictionary(dictionary, reader, jsonDictionaryContract, member, id); if (createdFromNonDefaultCreator) return jsonDictionaryContract.ParametrizedCreator(dictionary); if (dictionary is IWrappedDictionary) return ((IWrappedDictionary)dictionary).UnderlyingDictionary; return dictionary; } case JsonContractType.Dynamic: { JsonDynamicContract contract2 = (JsonDynamicContract)contract; return CreateDynamic(reader, contract2, member, id); } } string format = "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; format = format.FormatWith(CultureInfo.InvariantCulture, objectType2, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } private bool ReadMetadataPropertiesToken(JTokenReader 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.StartObject) { JObject jObject = (JObject)reader.CurrentToken; JToken jToken = jObject["$ref"]; if (jToken != null) { if (jToken.Type != JTokenType.String && jToken.Type != JTokenType.Null) throw JsonSerializationException.Create(jToken, jToken.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); JToken parent = jToken.Parent; JToken jToken2 = null; if (parent.Next != null) jToken2 = parent.Next; else if (parent.Previous != null) { jToken2 = parent.Previous; } string text = (string)jToken; if (text != null) { if (jToken2 != null) throw JsonSerializationException.Create(jToken2, jToken2.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); newValue = Serializer.GetReferenceResolver().ResolveReference(this, text); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text, newValue.GetType())), null); reader.Skip(); return true; } } JToken jToken3 = jObject["$type"]; if (jToken3 != null) { string qualifiedTypeName = (string)jToken3; JsonReader reader2 = jToken3.CreateReader(); CheckedRead(reader2); ResolveTypeName(reader2, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); JToken jToken4 = jObject["$value"]; if (jToken4 != null) { while (true) { CheckedRead(reader); if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "$value") break; CheckedRead(reader); reader.Skip(); } return false; } } JToken jToken5 = jObject["$id"]; if (jToken5 != null) id = (string)jToken5; JToken jToken6 = jObject["$values"]; if (jToken6 != null) { JsonReader reader3 = jToken6.CreateReader(); CheckedRead(reader3); newValue = CreateList(reader3, objectType, contract, member, existingValue, id); reader.Skip(); return true; } } CheckedRead(reader); return false; } private bool ReadMetadataProperties(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 qualifiedTypeName = reader.Value.ToString(); ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); 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 void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, string qualifiedTypeName) { if ((member?.TypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? containerMember?.ItemTypeNameHandling ?? Serializer._typeNameHandling) != 0) { ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName, 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, qualifiedTypeName), ex); } if ((object)type == null) throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); 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, qualifiedTypeName, 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); } } 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) { string format = "Cannot deserialize the current JSON array (e.g. [1,2,3]) 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 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." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } 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) { if (!jsonArrayContract.CanDeserialize) throw JsonSerializationException.Create(reader, "Cannot populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); return PopulateList(jsonArrayContract.ShouldCreateWrapper ? jsonArrayContract.CreateWrapper(existingValue) : ((IList)existingValue), reader, jsonArrayContract, member, id); } bool createdFromNonDefaultCreator; IList list = CreateNewList(reader, jsonArrayContract, out createdFromNonDefaultCreator); if (createdFromNonDefaultCreator) { 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 (!jsonArrayContract.HasParametrizedCreator && !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 (createdFromNonDefaultCreator) { if (jsonArrayContract.IsMultidimensionalArray) list = CollectionUtils.ToMultidimensionalArray(list, jsonArrayContract.CollectionItemType, contract.CreatedType.GetArrayRank()); else { if (!jsonArrayContract.IsArray) return jsonArrayContract.ParametrizedCreator(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) && JsonTokenUtils.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 createdFromNonDefaultCreator) { if (!contract.CanDeserialize) throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = 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); createdFromNonDefaultCreator = false; return (IList)obj; } if (contract.HasParametrizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); } 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)); 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 createdFromNonDefaultCreator) { if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = 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); createdFromNonDefaultCreator = false; return (IDictionary)obj; } if (contract.HasParametrizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } 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)); 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; if (!CheckPropertyName(reader, obj2.ToString())) try { try { DateParseHandling dateParseHandling; switch (primitiveTypeCode) { case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: dateParseHandling = DateParseHandling.DateTime; break; case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: dateParseHandling = DateParseHandling.DateTimeOffset; break; default: dateParseHandling = DateParseHandling.None; break; } obj2 = ((dateParseHandling == DateParseHandling.None || !DateTimeUtils.TryParseDateTime(obj2.ToString(), dateParseHandling, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out object 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 = JsonTokenUtils.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 CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor<object> creator, string id) { ValidationUtils.ArgumentNotNull(creator, "creator"); 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) { string arg = string.Join(", ", (from p in contract.CreatorParameters select p.PropertyName).ToArray()); TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, arg)), null); } IDictionary<string, object> extensionData; IDictionary<JsonProperty, object> dictionary2 = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, underlyingType, out extensionData); object[] array = new object[contract.CreatorParameters.Count]; IDictionary<JsonProperty, object> dictionary3 = new Dictionary<JsonProperty, object>(); foreach (KeyValuePair<JsonProperty, object> item in dictionary2) { JsonProperty property = item.Key; JsonProperty jsonProperty = (!contract.CreatorParameters.Contains(property)) ? contract.CreatorParameters.ForgivingCaseSensitiveFind((JsonProperty p) => p.PropertyName, property.UnderlyingName) : property; if (jsonProperty != null) { int num = contract.CreatorParameters.IndexOf(jsonProperty); array[num] = item.Value; } else dictionary3.Add(item); if (dictionary != null) { JsonProperty jsonProperty2 = dictionary.Keys.FirstOrDefault((JsonProperty p) => p.PropertyName == property.PropertyName); if (jsonProperty2 != null) dictionary[jsonProperty2] = ((item.Value == null) ? PropertyPresence.Null : PropertyPresence.Value); } } object obj = creator(array); if (id != null) AddReference(reader, id, obj); OnDeserializing(reader, contract, obj); foreach (KeyValuePair<JsonProperty, object> item2 in dictionary3) { JsonProperty key = item2.Key; object value = item2.Value; if (ShouldSetPropertyValue(key, value)) key.ValueProvider.SetValue(obj, value); else if (!key.Writable && value != null) { JsonContract jsonContract = Serializer._contractResolver.ResolveContract(key.PropertyType); if (jsonContract.ContractType == JsonContractType.Array) { JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract; object value2 = key.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 = key.ValueProvider.GetValue(obj); if (value3 != null) { IDictionary dictionary4 = jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(value3) : ((IDictionary)value3); IDictionary dictionary5 = jsonDictionaryContract.ShouldCreateWrapper ? jsonDictionaryContract.CreateWrapper(value) : ((IDictionary)value); IDictionaryEnumerator enumerator4 = dictionary5.GetEnumerator(); try { while (enumerator4.MoveNext()) { DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator4.Current; dictionary4.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> ResolvePropertyAndCreatorValues(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.CreatorParameters.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 createdFromNonDefaultCreator) { object obj = null; if (objectContract.OverrideCreator != null) { if (objectContract.CreatorParameters.Count > 0) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id); } obj = objectContract.OverrideCreator(); } else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedCreator == null)) { obj = objectContract.DefaultCreator(); } else if (objectContract.ParametrizedCreator != null) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id); } if (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)); 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)); } createdFromNonDefaultCreator = 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(); if (!CheckPropertyName(reader, text)) 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 bool CheckPropertyName(JsonReader reader, string memberName) { if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { switch (memberName) { case "$id": case "$ref": case "$type": case "$values": reader.Skip(); return true; } } return false; } 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.Ignored) 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()) { } } } } }