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

DefaultContractResolver

Used by JsonSerializer to resolves a JsonContract for a given Type.
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace Newtonsoft.Json.Serialization { public class DefaultContractResolver : IContractResolver { internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>, IEnumerable, IEnumerator<KeyValuePair<object, object>>, IEnumerator, IDisposable { private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e; public KeyValuePair<object, object> Current => new KeyValuePair<object, object>(_e.Current.Key, _e.Current.Value); object IEnumerator.Current { get { return Current; } } public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e) { ValidationUtils.ArgumentNotNull(e, "e"); _e = e.GetEnumerator(); } public bool MoveNext() { return _e.MoveNext(); } public void Reset() { _e.Reset(); } public void Dispose() { _e.Dispose(); } public IEnumerator<KeyValuePair<object, object>> GetEnumerator() { return this; } IEnumerator IEnumerable.GetEnumerator() { return this; } } private static readonly IContractResolver _instance = new DefaultContractResolver(true); private static readonly IList<JsonConverter> BuiltInConverters = new List<JsonConverter> { new ExpandoObjectConverter(), new XmlNodeConverter(), new JsonValueConverter(), new KeyValuePairConverter(), new BsonObjectIdConverter(), new RegexConverter(), new DiscriminatedUnionConverter() }; private static Dictionary<ResolverContractKey, JsonContract> _sharedContractCache; private static readonly object _typeContractCacheLock = new object(); private Dictionary<ResolverContractKey, JsonContract> _instanceContractCache; private readonly bool _sharedCache; private Newtonsoft.Json.Utilities.BindingFlags DefaultMembersSearchFlags = Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public; internal static IContractResolver Instance => _instance; public bool DynamicCodeGeneration => JsonTypeReflector.DynamicCodeGeneration; public bool SerializeCompilerGeneratedMembers { get; set; } public DefaultContractResolver() : this(false) { } public DefaultContractResolver(bool shareCache) { _sharedCache = shareCache; } private Dictionary<ResolverContractKey, JsonContract> GetCache() { if (_sharedCache) return _sharedContractCache; return _instanceContractCache; } private void UpdateCache(Dictionary<ResolverContractKey, JsonContract> cache) { if (_sharedCache) _sharedContractCache = cache; else _instanceContractCache = cache; } public virtual JsonContract ResolveContract(Type type) { if ((object)type == null) throw new ArgumentNullException("type"); ResolverContractKey key = new ResolverContractKey(GetType(), type); Dictionary<ResolverContractKey, JsonContract> cache = GetCache(); if (cache == null || !cache.TryGetValue(key, out JsonContract value)) { value = CreateContract(type); lock (_typeContractCacheLock) { cache = GetCache(); Dictionary<ResolverContractKey, JsonContract> dictionary = (cache != null) ? new Dictionary<ResolverContractKey, JsonContract>(cache) : new Dictionary<ResolverContractKey, JsonContract>(); dictionary[key] = value; UpdateCache(dictionary); return value; } } return value; } protected virtual List<MemberInfo> GetSerializableMembers(Type objectType) { bool ignoreSerializableAttribute = true; MemberSerialization objectMemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute); List<MemberInfo> list = (from m in ReflectionUtils.GetFieldsAndProperties(objectType, Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Static | Newtonsoft.Json.Utilities.BindingFlags.Public | Newtonsoft.Json.Utilities.BindingFlags.NonPublic) where !ReflectionUtils.IsIndexedProperty(m) select m).ToList(); List<MemberInfo> list2 = new List<MemberInfo>(); if (objectMemberSerialization == MemberSerialization.Fields) { foreach (MemberInfo item in list) { FieldInfo fieldInfo = item as FieldInfo; if ((object)fieldInfo != null && !fieldInfo.IsStatic) list2.Add(item); } return list2; } DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); List<MemberInfo> list3 = (from m in ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags) where !ReflectionUtils.IsIndexedProperty(m) select m).ToList(); foreach (MemberInfo item2 in list) { if (SerializeCompilerGeneratedMembers || !CustomAttributeExtensions.IsDefined(item2, typeof(CompilerGeneratedAttribute), true)) { if (list3.Contains(item2)) list2.Add(item2); else if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(item2) != null) { list2.Add(item2); } else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute<DataMemberAttribute>(item2) != null) { list2.Add(item2); } else if (objectMemberSerialization == MemberSerialization.Fields && item2.MemberType() == Newtonsoft.Json.Utilities.MemberTypes.Field) { list2.Add(item2); } } } if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", out Type _)) list2 = list2.Where(ShouldSerializeEntityMember).ToList(); return list2; } private bool ShouldSerializeEntityMember(MemberInfo memberInfo) { PropertyInfo propertyInfo = memberInfo as PropertyInfo; if ((object)propertyInfo != null && propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1") return false; return true; } protected virtual JsonObjectContract CreateObjectContract(Type objectType) { JsonObjectContract jsonObjectContract = new JsonObjectContract(objectType); InitializeContract(jsonObjectContract); bool ignoreSerializableAttribute = true; jsonObjectContract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(jsonObjectContract.NonNullableUnderlyingType, ignoreSerializableAttribute); jsonObjectContract.Properties.AddRange(CreateProperties(jsonObjectContract.NonNullableUnderlyingType, jsonObjectContract.MemberSerialization)); JsonObjectAttribute jsonObjectAttribute = JsonTypeReflector.GetJsonObjectAttribute(jsonObjectContract.NonNullableUnderlyingType); if (jsonObjectAttribute != null) jsonObjectContract.ItemRequired = jsonObjectAttribute._itemRequired; ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonObjectContract.NonNullableUnderlyingType); if ((object)attributeConstructor != null) { jsonObjectContract.OverrideConstructor = attributeConstructor; jsonObjectContract.ConstructorParameters.AddRange(CreateConstructorParameters(attributeConstructor, jsonObjectContract.Properties)); } else if (jsonObjectContract.MemberSerialization != MemberSerialization.Fields && (jsonObjectContract.DefaultCreator == null || jsonObjectContract.DefaultCreatorNonPublic)) { ConstructorInfo parametrizedConstructor = GetParametrizedConstructor(jsonObjectContract.NonNullableUnderlyingType); if ((object)parametrizedConstructor != null) { jsonObjectContract.ParametrizedConstructor = parametrizedConstructor; jsonObjectContract.ConstructorParameters.AddRange(CreateConstructorParameters(parametrizedConstructor, jsonObjectContract.Properties)); } } MemberInfo extensionDataMemberForType = GetExtensionDataMemberForType(jsonObjectContract.NonNullableUnderlyingType); if ((object)extensionDataMemberForType != null) SetExtensionDataDelegates(jsonObjectContract, extensionDataMemberForType); return jsonObjectContract; } private MemberInfo GetExtensionDataMemberForType(Type type) { IEnumerable<MemberInfo> source = GetClassHierarchyForType(type).SelectMany(delegate(Type baseType) { IList<MemberInfo> list = new List<MemberInfo>(); list.AddRange(baseType.GetProperties(Newtonsoft.Json.Utilities.BindingFlags.DeclaredOnly | Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public | Newtonsoft.Json.Utilities.BindingFlags.NonPublic)); list.AddRange(baseType.GetFields(Newtonsoft.Json.Utilities.BindingFlags.DeclaredOnly | Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public | Newtonsoft.Json.Utilities.BindingFlags.NonPublic)); return list; }); return source.LastOrDefault(delegate(MemberInfo m) { Newtonsoft.Json.Utilities.MemberTypes memberTypes = m.MemberType(); if (memberTypes != 0 && memberTypes != Newtonsoft.Json.Utilities.MemberTypes.Field) return false; if (!CustomAttributeExtensions.IsDefined(m, typeof(JsonExtensionDataAttribute), false)) return false; Type memberUnderlyingType = ReflectionUtils.GetMemberUnderlyingType(m); if (ReflectionUtils.ImplementsGenericDefinition(memberUnderlyingType, typeof(IDictionary<, >), out Type implementingType)) { Type type2 = TypeExtensions.GetGenericArguments(implementingType)[0]; Type type3 = TypeExtensions.GetGenericArguments(implementingType)[1]; if (TypeExtensions.IsAssignableFrom(type2, typeof(string)) && TypeExtensions.IsAssignableFrom(type3, typeof(JToken))) return true; } throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary<string, JToken>.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); }); } private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member) { JsonExtensionDataAttribute attribute = ReflectionUtils.GetAttribute<JsonExtensionDataAttribute>(member); if (attribute != null) { Type type = ReflectionUtils.GetMemberUnderlyingType(member); ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<, >), out Type implementingType); Type type2 = TypeExtensions.GetGenericArguments(implementingType)[0]; Type type3 = TypeExtensions.GetGenericArguments(implementingType)[1]; bool isJTokenValueType = typeof(JToken).IsAssignableFrom(type3); if (ReflectionUtils.IsGenericDefinition(type, typeof(IDictionary<, >))) type = typeof(Dictionary<, >).MakeGenericType(type2, type3); MethodInfo method = TypeExtensions.GetMethod(type, "Add", new Type[2] { type2, type3 }); Func<object, object> getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(member); Action<object, object> setExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(member); Func<object> createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(type); MethodCall<object, object> setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(method); ExtensionDataSetter extensionDataSetter = delegate(object o, string key, object value) { object obj2 = getExtensionDataDictionary(o); if (obj2 == null) { obj2 = createExtensionDataDictionary(); setExtensionDataDictionary(o, obj2); } if (isJTokenValueType && !(value is JToken)) value = JToken.FromObject(value); setExtensionDataDictionaryValue(obj2, key, value); }; Type type4 = typeof(DictionaryEnumerator<, >).MakeGenericType(type2, type3); ConstructorInfo method2 = TypeExtensions.GetConstructors(type4).First(); MethodCall<object, object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(method2); ExtensionDataGetter extensionDataGetter = delegate(object o) { object obj = getExtensionDataDictionary(o); if (obj == null) return null; return (IEnumerable<KeyValuePair<object, object>>)createEnumerableWrapper(null, obj); }; if (attribute.ReadData) contract.ExtensionDataSetter = extensionDataSetter; if (attribute.WriteData) contract.ExtensionDataGetter = extensionDataGetter; } } private ConstructorInfo GetAttributeConstructor(Type objectType) { IList<ConstructorInfo> list = (from c in objectType.GetConstructors(Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public | Newtonsoft.Json.Utilities.BindingFlags.NonPublic) where CustomAttributeExtensions.IsDefined(c, typeof(JsonConstructorAttribute), true) select c).ToList(); if (list.Count > 1) throw new JsonException("Multiple constructors with the JsonConstructorAttribute."); if (list.Count == 1) return list[0]; if ((object)objectType == typeof(Version)) return TypeExtensions.GetConstructor(objectType, new Type[4] { typeof(int), typeof(int), typeof(int), typeof(int) }); return null; } private ConstructorInfo GetParametrizedConstructor(Type objectType) { IList<ConstructorInfo> list = objectType.GetConstructors(Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public).ToList(); if (list.Count == 1) return list[0]; return null; } protected virtual IList<JsonProperty> CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties) { ParameterInfo[] parameters = constructor.GetParameters(); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(constructor.DeclaringType); ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { JsonProperty jsonProperty = (parameterInfo.Name != null) ? memberProperties.GetClosestMatchProperty(parameterInfo.Name) : null; if (jsonProperty != null && (object)jsonProperty.PropertyType != parameterInfo.ParameterType) jsonProperty = null; if (jsonProperty != null || parameterInfo.Name != null) { JsonProperty jsonProperty2 = CreatePropertyFromConstructorParameter(jsonProperty, parameterInfo); if (jsonProperty2 != null) jsonPropertyCollection.AddProperty(jsonProperty2); } } return jsonPropertyCollection; } protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = parameterInfo.ParameterType; SetPropertySettingsFromAttributes(jsonProperty, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out bool _); jsonProperty.Readable = false; jsonProperty.Writable = true; if (matchingMemberProperty != null) { jsonProperty.PropertyName = ((jsonProperty.PropertyName != parameterInfo.Name) ? jsonProperty.PropertyName : matchingMemberProperty.PropertyName); jsonProperty.Converter = (jsonProperty.Converter ?? matchingMemberProperty.Converter); jsonProperty.MemberConverter = (jsonProperty.MemberConverter ?? matchingMemberProperty.MemberConverter); if (!jsonProperty._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue) jsonProperty.DefaultValue = matchingMemberProperty.DefaultValue; jsonProperty._required = (jsonProperty._required ?? matchingMemberProperty._required); jsonProperty.IsReference = (jsonProperty.IsReference ?? matchingMemberProperty.IsReference); jsonProperty.NullValueHandling = (jsonProperty.NullValueHandling ?? matchingMemberProperty.NullValueHandling); jsonProperty.DefaultValueHandling = (jsonProperty.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling); jsonProperty.ReferenceLoopHandling = (jsonProperty.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling); jsonProperty.ObjectCreationHandling = (jsonProperty.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling); jsonProperty.TypeNameHandling = (jsonProperty.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling); } return jsonProperty; } protected virtual JsonConverter ResolveContractConverter(Type objectType) { return JsonTypeReflector.GetJsonConverter(objectType, objectType); } private Func<object> GetDefaultCreator(Type createdType) { return JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(createdType); } [SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")] private void InitializeContract(JsonContract contract) { JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetJsonContainerAttribute(contract.NonNullableUnderlyingType); if (jsonContainerAttribute != null) contract.IsReference = jsonContainerAttribute._isReference; else { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); if (dataContractAttribute != null && dataContractAttribute.IsReference) contract.IsReference = true; } contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType); contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType); if (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true) || contract.CreatedType.IsValueType()) { contract.DefaultCreator = GetDefaultCreator(contract.CreatedType); contract.DefaultCreatorNonPublic = (!contract.CreatedType.IsValueType() && (object)ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null); } ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType); } private void ResolveCallbackMethods(JsonContract contract, Type t) { GetCallbackMethodsForType(t, out List<SerializationCallback> onSerializing, out List<SerializationCallback> onSerialized, out List<SerializationCallback> onDeserializing, out List<SerializationCallback> onDeserialized, out List<SerializationErrorCallback> onError); if (onSerializing != null && (!t.IsGenericType() || (object)t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<, >))) contract.OnSerializingCallbacks.AddRange(onSerializing); if (onSerialized != null) contract.OnSerializedCallbacks.AddRange(onSerialized); if (onDeserializing != null) contract.OnDeserializingCallbacks.AddRange(onDeserializing); if (onDeserialized != null && (!t.IsGenericType() || (object)t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<, >))) contract.OnDeserializedCallbacks.AddRange(onDeserialized); if (onError != null) contract.OnErrorCallbacks.AddRange(onError); } private void GetCallbackMethodsForType(Type type, out List<SerializationCallback> onSerializing, out List<SerializationCallback> onSerialized, out List<SerializationCallback> onDeserializing, out List<SerializationCallback> onDeserialized, out List<SerializationErrorCallback> onError) { onSerializing = null; onSerialized = null; onDeserializing = null; onDeserialized = null; onError = null; foreach (Type item in GetClassHierarchyForType(type)) { MethodInfo currentCallback = null; MethodInfo currentCallback2 = null; MethodInfo currentCallback3 = null; MethodInfo currentCallback4 = null; MethodInfo currentCallback5 = null; foreach (MethodInfo method in item.GetMethods(Newtonsoft.Json.Utilities.BindingFlags.DeclaredOnly | Newtonsoft.Json.Utilities.BindingFlags.Instance | Newtonsoft.Json.Utilities.BindingFlags.Public | Newtonsoft.Json.Utilities.BindingFlags.NonPublic)) { if (!method.ContainsGenericParameters) { Type prevAttributeType = null; ParameterInfo[] parameters = method.GetParameters(); if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentCallback, ref prevAttributeType)) { onSerializing = (onSerializing ?? new List<SerializationCallback>()); onSerializing.Add(JsonContract.CreateSerializationCallback(method)); currentCallback = method; } if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentCallback2, ref prevAttributeType)) { onSerialized = (onSerialized ?? new List<SerializationCallback>()); onSerialized.Add(JsonContract.CreateSerializationCallback(method)); currentCallback2 = method; } if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentCallback3, ref prevAttributeType)) { onDeserializing = (onDeserializing ?? new List<SerializationCallback>()); onDeserializing.Add(JsonContract.CreateSerializationCallback(method)); currentCallback3 = method; } if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentCallback4, ref prevAttributeType)) { onDeserialized = (onDeserialized ?? new List<SerializationCallback>()); onDeserialized.Add(JsonContract.CreateSerializationCallback(method)); currentCallback4 = method; } if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentCallback5, ref prevAttributeType)) { onError = (onError ?? new List<SerializationErrorCallback>()); onError.Add(JsonContract.CreateSerializationErrorCallback(method)); currentCallback5 = method; } } } } } private List<Type> GetClassHierarchyForType(Type type) { List<Type> list = new List<Type>(); Type type2 = type; while ((object)type2 != null && (object)type2 != typeof(object)) { list.Add(type2); type2 = type2.BaseType(); } list.Reverse(); return list; } protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract jsonDictionaryContract = new JsonDictionaryContract(objectType); InitializeContract(jsonDictionaryContract); jsonDictionaryContract.PropertyNameResolver = ResolvePropertyName; return jsonDictionaryContract; } protected virtual JsonArrayContract CreateArrayContract(Type objectType) { JsonArrayContract jsonArrayContract = new JsonArrayContract(objectType); InitializeContract(jsonArrayContract); return jsonArrayContract; } protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType) { JsonPrimitiveContract jsonPrimitiveContract = new JsonPrimitiveContract(objectType); InitializeContract(jsonPrimitiveContract); return jsonPrimitiveContract; } protected virtual JsonLinqContract CreateLinqContract(Type objectType) { JsonLinqContract jsonLinqContract = new JsonLinqContract(objectType); InitializeContract(jsonLinqContract); return jsonLinqContract; } protected virtual JsonDynamicContract CreateDynamicContract(Type objectType) { JsonDynamicContract jsonDynamicContract = new JsonDynamicContract(objectType); InitializeContract(jsonDynamicContract); jsonDynamicContract.PropertyNameResolver = ResolvePropertyName; jsonDynamicContract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut)); return jsonDynamicContract; } protected virtual JsonStringContract CreateStringContract(Type objectType) { JsonStringContract jsonStringContract = new JsonStringContract(objectType); InitializeContract(jsonStringContract); return jsonStringContract; } protected virtual JsonContract CreateContract(Type objectType) { Type type = ReflectionUtils.EnsureNotNullableType(objectType); if (IsJsonPrimitiveType(objectType)) return CreatePrimitiveContract(objectType); if (JsonTypeReflector.GetJsonObjectAttribute(type) != null) return CreateObjectContract(objectType); if (JsonTypeReflector.GetJsonArrayAttribute(type) != null) return CreateArrayContract(objectType); if (JsonTypeReflector.GetJsonDictionaryAttribute(type) != null) return CreateDictionaryContract(objectType); if ((object)type == typeof(JToken) || TypeExtensions.IsSubclassOf(type, typeof(JToken))) return CreateLinqContract(objectType); if (CollectionUtils.IsDictionaryType(type)) return CreateDictionaryContract(objectType); if (typeof(IEnumerable).IsAssignableFrom(type)) return CreateArrayContract(objectType); if (CanConvertToString(type)) return CreateStringContract(objectType); if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(type)) return CreateDynamicContract(objectType); return CreateObjectContract(objectType); } internal static bool IsJsonPrimitiveType(Type t) { PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t); if (typeCode != 0) return typeCode != PrimitiveTypeCode.Object; return false; } internal static bool CanConvertToString(Type type) { if ((object)type == typeof(Type) || TypeExtensions.IsSubclassOf(type, typeof(Type))) return true; return false; } private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType) { if (!CustomAttributeExtensions.IsDefined(method, attributeType, false)) return false; if ((object)currentCallback != null) throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType)); if ((object)prevAttributeType != null) throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method)); if (method.IsVirtual) throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType)); if ((object)method.ReturnType != typeof(void)) throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method)); if ((object)attributeType == typeof(OnErrorAttribute)) { if (parameters == null || parameters.Length != 2 || (object)parameters[0].ParameterType != typeof(StreamingContext) || (object)parameters[1].ParameterType != typeof(ErrorContext)) throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext))); } else if (parameters == null || parameters.Length != 1 || (object)parameters[0].ParameterType != typeof(StreamingContext)) { throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext))); } prevAttributeType = attributeType; return true; } internal static string GetClrTypeFullName(Type type) { if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters()) return type.FullName; return string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[2] { type.Namespace, type.get_Name() }); } protected virtual IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { List<MemberInfo> serializableMembers = GetSerializableMembers(type); if (serializableMembers == null) throw new JsonSerializationException("Null collection of seralizable members returned."); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(type); foreach (MemberInfo item in serializableMembers) { JsonProperty jsonProperty = CreateProperty(item, memberSerialization); if (jsonProperty != null) jsonPropertyCollection.AddProperty(jsonProperty); } return (from p in jsonPropertyCollection orderby p.Order ?? (-1) select p).ToList(); } protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) { return new ExpressionValueProvider(member); } protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); jsonProperty.DeclaringType = member.DeclaringType; jsonProperty.ValueProvider = CreateMemberValueProvider(member); SetPropertySettingsFromAttributes(jsonProperty, member, member.Name, member.DeclaringType, memberSerialization, out bool allowNonPublicAccess); if (memberSerialization != MemberSerialization.Fields) { jsonProperty.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess); jsonProperty.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, jsonProperty.HasMemberAttribute); } else { jsonProperty.Readable = true; jsonProperty.Writable = true; } jsonProperty.ShouldSerialize = CreateShouldSerializeTest(member); SetIsSpecifiedActions(jsonProperty, member, allowNonPublicAccess); return jsonProperty; } private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess) { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); MemberInfo memberInfo = attributeProvider as MemberInfo; DataMemberAttribute dataMemberAttribute = (dataContractAttribute == null || (object)memberInfo == null) ? null : JsonTypeReflector.GetDataMemberAttribute(memberInfo); JsonPropertyAttribute attribute = JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(attributeProvider); if (attribute != null) property.HasMemberAttribute = true; string propertyName = (attribute != null && attribute.PropertyName != null) ? attribute.PropertyName : ((dataMemberAttribute == null || dataMemberAttribute.Name == null) ? name : dataMemberAttribute.Name); property.PropertyName = ResolvePropertyName(propertyName); property.UnderlyingName = name; bool flag = false; if (attribute != null) { property._required = attribute._required; property.Order = attribute._order; property.DefaultValueHandling = attribute._defaultValueHandling; flag = true; } else if (dataMemberAttribute != null) { property._required = (dataMemberAttribute.IsRequired ? Required.AllowNull : Required.Default); property.Order = ((dataMemberAttribute.Order != -1) ? new int?(dataMemberAttribute.Order) : null); property.DefaultValueHandling = ((!dataMemberAttribute.EmitDefaultValue) ? new DefaultValueHandling?(DefaultValueHandling.Ignore) : null); flag = true; } bool flag2 = JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null || JsonTypeReflector.GetAttribute<JsonExtensionDataAttribute>(attributeProvider) != null; if (memberSerialization != MemberSerialization.OptIn) { bool flag3 = false; flag3 = (JsonTypeReflector.GetAttribute<IgnoreDataMemberAttribute>(attributeProvider) != null); property.Ignored = (flag2 || flag3); } else property.Ignored = (flag2 || !flag); property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider, property.PropertyType); property.MemberConverter = JsonTypeReflector.GetJsonConverter(attributeProvider, property.PropertyType); DefaultValueAttribute attribute2 = JsonTypeReflector.GetAttribute<DefaultValueAttribute>(attributeProvider); if (attribute2 != null) property.DefaultValue = attribute2.Value; property.NullValueHandling = attribute?._nullValueHandling; property.ReferenceLoopHandling = attribute?._referenceLoopHandling; property.ObjectCreationHandling = attribute?._objectCreationHandling; property.TypeNameHandling = attribute?._typeNameHandling; property.IsReference = attribute?._isReference; property.ItemIsReference = attribute?._itemIsReference; property.ItemConverter = ((attribute != null && (object)attribute.ItemConverterType != null) ? JsonConverterAttribute.CreateJsonConverterInstance(attribute.ItemConverterType) : null); property.ItemReferenceLoopHandling = attribute?._itemReferenceLoopHandling; property.ItemTypeNameHandling = attribute?._itemTypeNameHandling; allowNonPublicAccess = false; if ((DefaultMembersSearchFlags & Newtonsoft.Json.Utilities.BindingFlags.NonPublic) == Newtonsoft.Json.Utilities.BindingFlags.NonPublic) allowNonPublicAccess = true; if (attribute != null) allowNonPublicAccess = true; if (memberSerialization == MemberSerialization.Fields) allowNonPublicAccess = true; if (dataMemberAttribute != null) { allowNonPublicAccess = true; property.HasMemberAttribute = true; } } private Predicate<object> CreateShouldSerializeTest(MemberInfo member) { MethodInfo method = TypeExtensions.GetMethod(member.DeclaringType, "ShouldSerialize" + member.Name, ReflectionUtils.EmptyTypes); if ((object)method == null || (object)method.ReturnType != typeof(bool)) return null; MethodCall<object, object> shouldSerializeCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(method); return (object o) => (bool)shouldSerializeCall(o); } private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) { MemberInfo memberInfo = TypeExtensions.GetProperty(member.DeclaringType, member.Name + "Specified"); if ((object)memberInfo == null) memberInfo = TypeExtensions.GetField(member.DeclaringType, member.Name + "Specified"); if ((object)memberInfo != null && (object)ReflectionUtils.GetMemberUnderlyingType(memberInfo) == typeof(bool)) { Func<object, object> specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(memberInfo); property.GetIsSpecified = ((object o) => (bool)specifiedPropertyGet(o)); if (ReflectionUtils.CanSetMemberValue(memberInfo, allowNonPublicAccess, false)) property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(memberInfo); } } protected internal virtual string ResolvePropertyName(string propertyName) { return propertyName; } public string GetResolvedPropertyName(string propertyName) { return ResolvePropertyName(propertyName); } } }