JsonSerializerInternalReader
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Utilities.LinqBridge;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
namespace Newtonsoft.Json.Serialization
{
internal class JsonSerializerInternalReader : JsonSerializerInternalBase
{
internal enum PropertyPresence
{
None,
Null,
Value
}
private JsonSerializerProxy _internalSerializer;
private JsonFormatterConverter _formatterConverter;
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 JsonFormatterConverter GetFormatterConverter()
{
if (_formatterConverter == null)
_formatterConverter = new JsonFormatterConverter(GetInternalSerializer());
return _formatterConverter;
}
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();
do {
if (reader.TokenType != JsonToken.PropertyName) {
jTokenWriter.WriteEndObject();
return jTokenWriter.Token;
}
string text = (string)reader.Value;
if (!reader.Read())
break;
if (!CheckPropertyName(reader, text)) {
jTokenWriter.WritePropertyName(text);
jTokenWriter.WriteToken(reader, true, true);
}
} 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:
if ((object)objectType == typeof(DBNull))
return DBNull.Value;
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.Serializable:
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;
object newValue;
string id;
if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) {
JTokenReader jTokenReader = reader as JTokenReader;
if (jTokenReader == null) {
JToken jToken = JToken.ReadFrom(reader);
jTokenReader = (JTokenReader)jToken.CreateReader();
CheckedRead(jTokenReader);
reader = jTokenReader;
}
if (ReadMetadataPropertiesToken(jTokenReader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
return newValue;
} else {
CheckedRead(reader);
if (ReadMetadataProperties(reader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out newValue, out 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 || ((object)objectType2 != objectType && !objectType2.IsAssignableFrom(existingValue.GetType()))) ? 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, 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 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.Serializable: {
JsonISerializableContract contract2 = (JsonISerializableContract)contract;
return CreateISerializable(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, objectType2, GetExpectedDescription(contract)));
}
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._current;
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 && !objectType.IsAssignableFrom(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)
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, 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))
return contract.ContractType == JsonContractType.Linq;
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);
}
return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
} 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;
if (!CheckPropertyName(reader, obj2.ToString()))
try {
try {
DateParseHandling dateParseHandling;
switch (primitiveTypeCode) {
case PrimitiveTypeCode.DateTime:
case PrimitiveTypeCode.DateTimeNullable:
dateParseHandling = DateParseHandling.DateTime;
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 CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, string id)
{
Type underlyingType = contract.UnderlyingType;
if (!JsonTypeReflector.FullyTrusted)
throw JsonSerializationException.Create(reader, "Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data.\r\nTo fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.\r\n".FormatWith(CultureInfo.InvariantCulture, underlyingType));
if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using ISerializable constructor.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, GetFormatterConverter());
bool flag = false;
do {
switch (reader.TokenType) {
case JsonToken.PropertyName: {
string text = reader.Value.ToString();
if (!reader.Read())
throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text));
if (reader.TokenType == JsonToken.StartObject) {
object value = CreateObject(reader, null, null, null, contract, member, null);
serializationInfo.AddValue(text, value);
} else
serializationInfo.AddValue(text, JToken.ReadFrom(reader));
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, serializationInfo, "Unexpected end when deserializing object.");
if (contract.ISerializableCreator == null)
throw JsonSerializationException.Create(reader, "ISerializable type '{0}' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present.".FormatWith(CultureInfo.InvariantCulture, underlyingType));
object obj = contract.ISerializableCreator(serializationInfo, Serializer._context);
if (id != null)
AddReference(reader, id, obj);
OnDeserializing(reader, contract, obj);
OnDeserialized(reader, contract, obj);
return obj;
}
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.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;
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();
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.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.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()) {
}
}
}
}
}