You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1695 lines
72 KiB

4 years ago
4 years ago
4 years ago
4 years ago
  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections;
  27. #if !NET20
  28. using System.Collections.Concurrent;
  29. #endif
  30. using Newtonsoft.Json.Schema;
  31. using System.Collections.Generic;
  32. using System.ComponentModel;
  33. #if !NET20
  34. using System.Dynamic;
  35. #endif
  36. using System.Globalization;
  37. using System.IO;
  38. using System.Reflection;
  39. using System.Runtime.Serialization;
  40. #if HAVE_CAS
  41. using System.Security.Permissions;
  42. #endif
  43. using Newtonsoft.Json.Converters;
  44. using Newtonsoft.Json.Utilities;
  45. using Newtonsoft.Json.Linq;
  46. using System.Runtime.CompilerServices;
  47. #if NET20
  48. using Newtonsoft.Json.Utilities.LinqBridge;
  49. #else
  50. using System.Linq;
  51. #endif
  52. using Newtonsoft.Json.Serialization;
  53. namespace Newtonsoft.Json.Serialization
  54. {
  55. /// <summary>
  56. /// Used by <see cref="JsonSerializer"/> to resolve a <see cref="JsonContract"/> for a given <see cref="System.Type"/>.
  57. /// </summary>
  58. internal class DefaultContractResolver : IContractResolver
  59. {
  60. private static readonly IContractResolver _instance = new DefaultContractResolver();
  61. // Json.NET Schema requires a property
  62. internal static IContractResolver Instance => _instance;
  63. private static readonly string[] BlacklistedTypeNames =
  64. {
  65. "System.IO.DriveInfo",
  66. "System.IO.FileInfo",
  67. "System.IO.DirectoryInfo"
  68. };
  69. private static readonly JsonConverter[] BuiltInConverters =
  70. {
  71. #if !NET20
  72. new EntityKeyMemberConverter(),
  73. #endif
  74. #if !NET20
  75. new ExpandoObjectConverter(),
  76. #endif
  77. new XmlNodeConverter(),
  78. #if HAVE_ADO_NET
  79. new BinaryConverter(),
  80. new DataSetConverter(),
  81. new DataTableConverter(),
  82. #endif
  83. #if !NET20
  84. new DiscriminatedUnionConverter(),
  85. #endif
  86. new KeyValuePairConverter(),
  87. #pragma warning disable 618
  88. new BsonObjectIdConverter(),
  89. #pragma warning restore 618
  90. new RegexConverter()
  91. };
  92. private readonly PropertyNameTable _nameTable = new PropertyNameTable();
  93. private readonly ThreadSafeStore<Type, JsonContract> _contractCache;
  94. /// <summary>
  95. /// Gets a value indicating whether members are being get and set using dynamic code generation.
  96. /// This value is determined by the runtime permissions available.
  97. /// </summary>
  98. /// <value>
  99. /// <c>true</c> if using dynamic code generation; otherwise, <c>false</c>.
  100. /// </value>
  101. public bool DynamicCodeGeneration => JsonTypeReflector.DynamicCodeGeneration;
  102. #if !PORTABLE
  103. /// <summary>
  104. /// Gets or sets the default members search flags.
  105. /// </summary>
  106. /// <value>The default members search flags.</value>
  107. [Obsolete("DefaultMembersSearchFlags is obsolete. To modify the members serialized inherit from DefaultContractResolver and override the GetSerializableMembers method instead.")]
  108. public BindingFlags DefaultMembersSearchFlags { get; set; }
  109. #else
  110. private BindingFlags DefaultMembersSearchFlags;
  111. #endif
  112. /// <summary>
  113. /// Gets or sets a value indicating whether compiler generated members should be serialized.
  114. /// </summary>
  115. /// <value>
  116. /// <c>true</c> if serialized compiler generated members; otherwise, <c>false</c>.
  117. /// </value>
  118. public bool SerializeCompilerGeneratedMembers { get; set; }
  119. #if HAVE_BINARY_SERIALIZATION
  120. /// <summary>
  121. /// Gets or sets a value indicating whether to ignore the <see cref="ISerializable"/> interface when serializing and deserializing types.
  122. /// </summary>
  123. /// <value>
  124. /// <c>true</c> if the <see cref="ISerializable"/> interface will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
  125. /// </value>
  126. public bool IgnoreSerializableInterface { get; set; }
  127. /// <summary>
  128. /// Gets or sets a value indicating whether to ignore the <see cref="SerializableAttribute"/> attribute when serializing and deserializing types.
  129. /// </summary>
  130. /// <value>
  131. /// <c>true</c> if the <see cref="SerializableAttribute"/> attribute will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
  132. /// </value>
  133. public bool IgnoreSerializableAttribute { get; set; }
  134. #endif
  135. /// <summary>
  136. /// Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types.
  137. /// </summary>
  138. /// <value>
  139. /// <c>true</c> if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
  140. /// </value>
  141. public bool IgnoreIsSpecifiedMembers { get; set; }
  142. /// <summary>
  143. /// Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types.
  144. /// </summary>
  145. /// <value>
  146. /// <c>true</c> if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
  147. /// </value>
  148. public bool IgnoreShouldSerializeMembers { get; set; }
  149. /// <summary>
  150. /// Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized.
  151. /// </summary>
  152. /// <value>The naming strategy used to resolve how property names and dictionary keys are serialized.</value>
  153. public NamingStrategy NamingStrategy { get; set; }
  154. /// <summary>
  155. /// Initializes a new instance of the <see cref="DefaultContractResolver"/> class.
  156. /// </summary>
  157. public DefaultContractResolver()
  158. {
  159. #if HAVE_BINARY_SERIALIZATION
  160. IgnoreSerializableAttribute = true;
  161. #endif
  162. #pragma warning disable 618
  163. DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public;
  164. #pragma warning restore 618
  165. _contractCache = new ThreadSafeStore<Type, JsonContract>(CreateContract);
  166. }
  167. /// <summary>
  168. /// Resolves the contract for a given type.
  169. /// </summary>
  170. /// <param name="type">The type to resolve a contract for.</param>
  171. /// <returns>The contract for a given type.</returns>
  172. public virtual JsonContract ResolveContract(Type type)
  173. {
  174. ValidationUtils.ArgumentNotNull(type, nameof(type));
  175. return _contractCache.Get(type);
  176. }
  177. /// <summary>
  178. /// Gets the serializable members for the type.
  179. /// </summary>
  180. /// <param name="objectType">The type to get serializable members for.</param>
  181. /// <returns>The serializable members for the type.</returns>
  182. protected virtual List<MemberInfo> GetSerializableMembers(Type objectType)
  183. {
  184. bool ignoreSerializableAttribute;
  185. #if HAVE_BINARY_SERIALIZATION
  186. ignoreSerializableAttribute = IgnoreSerializableAttribute;
  187. #else
  188. ignoreSerializableAttribute = true;
  189. #endif
  190. MemberSerialization memberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute);
  191. IEnumerable<MemberInfo> allMembers = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
  192. .Where(m => !ReflectionUtils.IsIndexedProperty(m));
  193. List<MemberInfo> serializableMembers = new List<MemberInfo>();
  194. if (memberSerialization != MemberSerialization.Fields)
  195. {
  196. #if !NET20
  197. DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType);
  198. #endif
  199. #pragma warning disable 618
  200. List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags)
  201. .Where(m => !ReflectionUtils.IsIndexedProperty(m)).List();
  202. #pragma warning restore 618
  203. foreach (MemberInfo member in allMembers)
  204. {
  205. // exclude members that are compiler generated if set
  206. if (SerializeCompilerGeneratedMembers || !member.IsDefined(typeof(CompilerGeneratedAttribute), true))
  207. {
  208. if (defaultMembers.Contains(member))
  209. {
  210. // add all members that are found by default member search
  211. serializableMembers.Add(member);
  212. }
  213. else
  214. {
  215. // add members that are explicitly marked with JsonProperty/DataMember attribute
  216. // or are a field if serializing just fields
  217. if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member) != null)
  218. {
  219. serializableMembers.Add(member);
  220. }
  221. else if (JsonTypeReflector.GetAttribute<JsonRequiredAttribute>(member) != null)
  222. {
  223. serializableMembers.Add(member);
  224. }
  225. #if !NET20
  226. else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute<DataMemberAttribute>(member) != null)
  227. {
  228. serializableMembers.Add(member);
  229. }
  230. #endif
  231. else if (memberSerialization == MemberSerialization.Fields && member.MemberType() == MemberTypes.Field)
  232. {
  233. serializableMembers.Add(member);
  234. }
  235. }
  236. }
  237. }
  238. #if !NET20
  239. Type match;
  240. // don't include EntityKey on entities objects... this is a bit hacky
  241. if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", false, out match))
  242. {
  243. serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).List();
  244. }
  245. #endif
  246. }
  247. else
  248. {
  249. // serialize all fields
  250. foreach (MemberInfo member in allMembers)
  251. {
  252. if (member is FieldInfo field && !field.IsStatic)
  253. {
  254. serializableMembers.Add(member);
  255. }
  256. }
  257. }
  258. return serializableMembers;
  259. }
  260. #if !NET20
  261. private bool ShouldSerializeEntityMember(MemberInfo memberInfo)
  262. {
  263. PropertyInfo propertyInfo = memberInfo as PropertyInfo;
  264. if (propertyInfo != null)
  265. {
  266. if (propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1")
  267. {
  268. return false;
  269. }
  270. }
  271. return true;
  272. }
  273. #endif
  274. /// <summary>
  275. /// Creates a <see cref="JsonObjectContract"/> for the given type.
  276. /// </summary>
  277. /// <param name="objectType">Type of the object.</param>
  278. /// <returns>A <see cref="JsonObjectContract"/> for the given type.</returns>
  279. protected virtual JsonObjectContract CreateObjectContract(Type objectType)
  280. {
  281. // serializing DirectoryInfo without ISerializable will stackoverflow
  282. // https://github.com/JamesNK/Newtonsoft.Json/issues/1541
  283. if (Array.IndexOf(BlacklistedTypeNames, objectType.FullName) != -1)
  284. {
  285. throw new JsonSerializationException("Unable to serialize instance of '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
  286. }
  287. JsonObjectContract contract = new JsonObjectContract(objectType);
  288. InitializeContract(contract);
  289. bool ignoreSerializableAttribute;
  290. #if HAVE_BINARY_SERIALIZATION
  291. ignoreSerializableAttribute = IgnoreSerializableAttribute;
  292. #else
  293. ignoreSerializableAttribute = true;
  294. #endif
  295. contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute);
  296. contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization));
  297. Func<string, string> extensionDataNameResolver = null;
  298. JsonObjectAttribute attribute = JsonTypeReflector.GetCachedAttribute<JsonObjectAttribute>(contract.NonNullableUnderlyingType);
  299. if (attribute != null)
  300. {
  301. contract.ItemRequired = attribute._itemRequired;
  302. contract.ItemNullValueHandling = attribute._itemNullValueHandling;
  303. if (attribute.NamingStrategyType != null)
  304. {
  305. NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute);
  306. extensionDataNameResolver = s => namingStrategy.GetDictionaryKey(s);
  307. }
  308. }
  309. if (extensionDataNameResolver == null)
  310. {
  311. extensionDataNameResolver = ResolveExtensionDataName;
  312. }
  313. contract.ExtensionDataNameResolver = extensionDataNameResolver;
  314. if (contract.IsInstantiable)
  315. {
  316. ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType);
  317. // check if a JsonConstructorAttribute has been defined and use that
  318. if (overrideConstructor != null)
  319. {
  320. contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor);
  321. contract.CreatorParameters.AddRange(CreateConstructorParameters(overrideConstructor, contract.Properties));
  322. }
  323. else if (contract.MemberSerialization == MemberSerialization.Fields)
  324. {
  325. #if HAVE_BINARY_FORMATTER
  326. // mimic DataContractSerializer behaviour when populating fields by overriding default creator to create an uninitialized object
  327. // note that this is only possible when the application is fully trusted so fall back to using the default constructor (if available) in partial trust
  328. if (JsonTypeReflector.FullyTrusted)
  329. {
  330. contract.DefaultCreator = contract.GetUninitializedObject;
  331. }
  332. #endif
  333. }
  334. else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
  335. {
  336. ConstructorInfo constructor = GetParameterizedConstructor(contract.NonNullableUnderlyingType);
  337. if (constructor != null)
  338. {
  339. contract.ParameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor);
  340. contract.CreatorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties));
  341. }
  342. }
  343. else if (contract.NonNullableUnderlyingType.IsValueType())
  344. {
  345. // value types always have default constructor
  346. // check whether there is a constructor that matches with non-writable properties on value type
  347. ConstructorInfo constructor = GetImmutableConstructor(contract.NonNullableUnderlyingType, contract.Properties);
  348. if (constructor != null)
  349. {
  350. contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor);
  351. contract.CreatorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties));
  352. }
  353. }
  354. }
  355. MemberInfo extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType);
  356. if (extensionDataMember != null)
  357. {
  358. SetExtensionDataDelegates(contract, extensionDataMember);
  359. }
  360. return contract;
  361. }
  362. private MemberInfo GetExtensionDataMemberForType(Type type)
  363. {
  364. IEnumerable<MemberInfo> members = GetClassHierarchyForType(type).SelectMany(baseType =>
  365. {
  366. IList<MemberInfo> m = new List<MemberInfo>();
  367. m.AddRange(baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
  368. m.AddRange(baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
  369. return m;
  370. });
  371. MemberInfo extensionDataMember = members.LastOrDefault(m =>
  372. {
  373. MemberTypes memberType = m.MemberType();
  374. if (memberType != MemberTypes.Property && memberType != MemberTypes.Field)
  375. {
  376. return false;
  377. }
  378. // last instance of attribute wins on type if there are multiple
  379. if (!m.IsDefined(typeof(JsonExtensionDataAttribute), false))
  380. {
  381. return false;
  382. }
  383. if (!ReflectionUtils.CanReadMemberValue(m, true))
  384. {
  385. throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name));
  386. }
  387. Type t = ReflectionUtils.GetMemberUnderlyingType(m);
  388. if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type dictionaryType))
  389. {
  390. Type keyType = dictionaryType.GetGenericArguments()[0];
  391. Type valueType = dictionaryType.GetGenericArguments()[1];
  392. if (keyType.IsAssignableFrom(typeof(string)) && valueType.IsAssignableFrom(typeof(JToken)))
  393. {
  394. return true;
  395. }
  396. }
  397. 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));
  398. });
  399. return extensionDataMember;
  400. }
  401. private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member)
  402. {
  403. JsonExtensionDataAttribute extensionDataAttribute = ReflectionUtils.GetAttribute<JsonExtensionDataAttribute>(member);
  404. if (extensionDataAttribute == null)
  405. {
  406. return;
  407. }
  408. Type t = ReflectionUtils.GetMemberUnderlyingType(member);
  409. ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type dictionaryType);
  410. Type keyType = dictionaryType.GetGenericArguments()[0];
  411. Type valueType = dictionaryType.GetGenericArguments()[1];
  412. Type createdType;
  413. // change type to a class if it is the base interface so it can be instantiated if needed
  414. if (ReflectionUtils.IsGenericDefinition(t, typeof(IDictionary<,>)))
  415. {
  416. createdType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
  417. }
  418. else
  419. {
  420. createdType = t;
  421. }
  422. Func<object, object> getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(member);
  423. if (extensionDataAttribute.ReadData)
  424. {
  425. Action<object, object> setExtensionDataDictionary = (ReflectionUtils.CanSetMemberValue(member, true, false))
  426. ? JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(member)
  427. : null;
  428. Func<object> createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(createdType);
  429. MethodInfo addMethod = t.GetMethod("Add", new[] { keyType, valueType });
  430. if (addMethod == null)
  431. {
  432. // Add is explicitly implemented and non-public
  433. // get from dictionary interface
  434. addMethod = dictionaryType.GetMethod("Add", new[] {keyType, valueType});
  435. }
  436. MethodCall<object, object> setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(addMethod);
  437. ExtensionDataSetter extensionDataSetter = (o, key, value) =>
  438. {
  439. object dictionary = getExtensionDataDictionary(o);
  440. if (dictionary == null)
  441. {
  442. if (setExtensionDataDictionary == null)
  443. {
  444. throw new JsonSerializationException("Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set.".FormatWith(CultureInfo.InvariantCulture, member.Name));
  445. }
  446. dictionary = createExtensionDataDictionary();
  447. setExtensionDataDictionary(o, dictionary);
  448. }
  449. setExtensionDataDictionaryValue(dictionary, key, value);
  450. };
  451. contract.ExtensionDataSetter = extensionDataSetter;
  452. }
  453. if (extensionDataAttribute.WriteData)
  454. {
  455. Type enumerableWrapper = typeof(EnumerableDictionaryWrapper<,>).MakeGenericType(keyType, valueType);
  456. ConstructorInfo constructors = Enumerable.First(enumerableWrapper.GetConstructors());
  457. ObjectConstructor<object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructors);
  458. ExtensionDataGetter extensionDataGetter = o =>
  459. {
  460. object dictionary = getExtensionDataDictionary(o);
  461. if (dictionary == null)
  462. {
  463. return null;
  464. }
  465. return (IEnumerable<KeyValuePair<object, object>>)createEnumerableWrapper(dictionary);
  466. };
  467. contract.ExtensionDataGetter = extensionDataGetter;
  468. }
  469. contract.ExtensionDataValueType = valueType;
  470. }
  471. // leave as class instead of struct
  472. // will be always return as an interface and boxed
  473. internal class EnumerableDictionaryWrapper<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>
  474. {
  475. private readonly IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
  476. internal EnumerableDictionaryWrapper(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
  477. {
  478. ValidationUtils.ArgumentNotNull(e, nameof(e));
  479. _e = e;
  480. }
  481. public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
  482. {
  483. foreach (KeyValuePair<TEnumeratorKey, TEnumeratorValue> item in _e)
  484. {
  485. yield return new KeyValuePair<object, object>(item.Key, item.Value);
  486. }
  487. }
  488. IEnumerator IEnumerable.GetEnumerator()
  489. {
  490. return GetEnumerator();
  491. }
  492. }
  493. private ConstructorInfo GetAttributeConstructor(Type objectType)
  494. {
  495. IEnumerator<ConstructorInfo> en = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).GetEnumerator();
  496. if (en.MoveNext())
  497. {
  498. ConstructorInfo conInfo = en.Current;
  499. if (en.MoveNext())
  500. {
  501. throw new JsonException("Multiple constructors with the JsonConstructorAttribute.");
  502. }
  503. return conInfo;
  504. }
  505. // little hack to get Version objects to deserialize correctly
  506. if (objectType == typeof(Version))
  507. {
  508. return objectType.GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int) });
  509. }
  510. return null;
  511. }
  512. private ConstructorInfo GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties)
  513. {
  514. IEnumerable<ConstructorInfo> constructors = objectType.GetConstructors();
  515. IEnumerator<ConstructorInfo> en = constructors.GetEnumerator();
  516. if (en.MoveNext())
  517. {
  518. ConstructorInfo constructor = en.Current;
  519. if (!en.MoveNext())
  520. {
  521. ParameterInfo[] parameters = constructor.GetParameters();
  522. if (parameters.Length > 0)
  523. {
  524. foreach (ParameterInfo parameterInfo in parameters)
  525. {
  526. JsonProperty memberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType);
  527. if (memberProperty == null || memberProperty.Writable)
  528. {
  529. return null;
  530. }
  531. }
  532. return constructor;
  533. }
  534. }
  535. }
  536. return null;
  537. }
  538. private ConstructorInfo GetParameterizedConstructor(Type objectType)
  539. {
  540. #if PORTABLE
  541. IEnumerable<ConstructorInfo> constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
  542. IEnumerator<ConstructorInfo> en = constructors.GetEnumerator();
  543. if (en.MoveNext())
  544. {
  545. ConstructorInfo conInfo = en.Current;
  546. if (!en.MoveNext())
  547. {
  548. return conInfo;
  549. }
  550. }
  551. #else
  552. ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
  553. if (constructors.Length == 1)
  554. {
  555. return constructors[0];
  556. }
  557. #endif
  558. return null;
  559. }
  560. /// <summary>
  561. /// Creates the constructor parameters.
  562. /// </summary>
  563. /// <param name="constructor">The constructor to create properties for.</param>
  564. /// <param name="memberProperties">The type's member properties.</param>
  565. /// <returns>Properties for the given <see cref="ConstructorInfo"/>.</returns>
  566. protected virtual IList<JsonProperty> CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties)
  567. {
  568. ParameterInfo[] constructorParameters = constructor.GetParameters();
  569. JsonPropertyCollection parameterCollection = new JsonPropertyCollection(constructor.DeclaringType);
  570. foreach (ParameterInfo parameterInfo in constructorParameters)
  571. {
  572. JsonProperty matchingMemberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType);
  573. // ensure that property will have a name from matching property or from parameterinfo
  574. // parameterinfo could have no name if generated by a proxy (I'm looking at you Castle)
  575. if (matchingMemberProperty != null || parameterInfo.Name != null)
  576. {
  577. JsonProperty property = CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);
  578. if (property != null)
  579. {
  580. parameterCollection.AddProperty(property);
  581. }
  582. }
  583. }
  584. return parameterCollection;
  585. }
  586. private JsonProperty MatchProperty(JsonPropertyCollection properties, string name, Type type)
  587. {
  588. // it is possible to generate a member with a null name using Reflection.Emit
  589. // protect against an ArgumentNullException from GetClosestMatchProperty by testing for null here
  590. if (name == null)
  591. {
  592. return null;
  593. }
  594. JsonProperty property = properties.GetClosestMatchProperty(name);
  595. // must match type as well as name
  596. if (property == null || property.PropertyType != type)
  597. {
  598. return null;
  599. }
  600. return property;
  601. }
  602. /// <summary>
  603. /// Creates a <see cref="JsonProperty"/> for the given <see cref="ParameterInfo"/>.
  604. /// </summary>
  605. /// <param name="matchingMemberProperty">The matching member property.</param>
  606. /// <param name="parameterInfo">The constructor parameter.</param>
  607. /// <returns>A created <see cref="JsonProperty"/> for the given <see cref="ParameterInfo"/>.</returns>
  608. protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo)
  609. {
  610. JsonProperty property = new JsonProperty();
  611. property.PropertyType = parameterInfo.ParameterType;
  612. property.AttributeProvider = new ReflectionAttributeProvider(parameterInfo);
  613. SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out _);
  614. property.Readable = false;
  615. property.Writable = true;
  616. // "inherit" values from matching member property if unset on parameter
  617. if (matchingMemberProperty != null)
  618. {
  619. property.PropertyName = (property.PropertyName != parameterInfo.Name) ? property.PropertyName : matchingMemberProperty.PropertyName;
  620. property.Converter = property.Converter ?? matchingMemberProperty.Converter;
  621. if (!property._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue)
  622. {
  623. property.DefaultValue = matchingMemberProperty.DefaultValue;
  624. }
  625. property._required = property._required ?? matchingMemberProperty._required;
  626. property.IsReference = property.IsReference ?? matchingMemberProperty.IsReference;
  627. property.NullValueHandling = property.NullValueHandling ?? matchingMemberProperty.NullValueHandling;
  628. property.DefaultValueHandling = property.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling;
  629. property.ReferenceLoopHandling = property.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling;
  630. property.ObjectCreationHandling = property.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling;
  631. property.TypeNameHandling = property.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling;
  632. }
  633. return property;
  634. }
  635. /// <summary>
  636. /// Resolves the default <see cref="JsonConverter" /> for the contract.
  637. /// </summary>
  638. /// <param name="objectType">Type of the object.</param>
  639. /// <returns>The contract's default <see cref="JsonConverter" />.</returns>
  640. protected virtual JsonConverter ResolveContractConverter(Type objectType)
  641. {
  642. return JsonTypeReflector.GetJsonConverter(objectType);
  643. }
  644. private Func<object> GetDefaultCreator(Type createdType)
  645. {
  646. return JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(createdType);
  647. }
  648. #if NET35
  649. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
  650. #endif
  651. private void InitializeContract(JsonContract contract)
  652. {
  653. JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(contract.NonNullableUnderlyingType);
  654. if (containerAttribute != null)
  655. {
  656. contract.IsReference = containerAttribute._isReference;
  657. }
  658. #if !NET20
  659. else
  660. {
  661. DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType);
  662. // doesn't have a null value
  663. if (dataContractAttribute != null && dataContractAttribute.IsReference)
  664. {
  665. contract.IsReference = true;
  666. }
  667. }
  668. #endif
  669. contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType);
  670. // then see whether object is compatible with any of the built in converters
  671. contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType);
  672. if (contract.IsInstantiable
  673. && (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true) || contract.CreatedType.IsValueType()))
  674. {
  675. contract.DefaultCreator = GetDefaultCreator(contract.CreatedType);
  676. contract.DefaultCreatorNonPublic = (!contract.CreatedType.IsValueType() &&
  677. ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null);
  678. }
  679. ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType);
  680. }
  681. private void ResolveCallbackMethods(JsonContract contract, Type t)
  682. {
  683. GetCallbackMethodsForType(
  684. t,
  685. out List<SerializationCallback> onSerializing,
  686. out List<SerializationCallback> onSerialized,
  687. out List<SerializationCallback> onDeserializing,
  688. out List<SerializationCallback> onDeserialized,
  689. out List<SerializationErrorCallback> onError);
  690. if (onSerializing != null)
  691. {
  692. contract.OnSerializingCallbacks.AddRange(onSerializing);
  693. }
  694. if (onSerialized != null)
  695. {
  696. contract.OnSerializedCallbacks.AddRange(onSerialized);
  697. }
  698. if (onDeserializing != null)
  699. {
  700. contract.OnDeserializingCallbacks.AddRange(onDeserializing);
  701. }
  702. if (onDeserialized != null)
  703. {
  704. contract.OnDeserializedCallbacks.AddRange(onDeserialized);
  705. }
  706. if (onError != null)
  707. {
  708. contract.OnErrorCallbacks.AddRange(onError);
  709. }
  710. }
  711. 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)
  712. {
  713. onSerializing = null;
  714. onSerialized = null;
  715. onDeserializing = null;
  716. onDeserialized = null;
  717. onError = null;
  718. foreach (Type baseType in GetClassHierarchyForType(type))
  719. {
  720. // while we allow more than one OnSerialized total, only one can be defined per class
  721. MethodInfo currentOnSerializing = null;
  722. MethodInfo currentOnSerialized = null;
  723. MethodInfo currentOnDeserializing = null;
  724. MethodInfo currentOnDeserialized = null;
  725. MethodInfo currentOnError = null;
  726. bool skipSerializing = ShouldSkipSerializing(baseType);
  727. bool skipDeserialized = ShouldSkipDeserialized(baseType);
  728. foreach (MethodInfo method in baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  729. {
  730. // compact framework errors when getting parameters for a generic method
  731. // lame, but generic methods should not be callbacks anyway
  732. if (method.ContainsGenericParameters)
  733. {
  734. continue;
  735. }
  736. Type prevAttributeType = null;
  737. ParameterInfo[] parameters = method.GetParameters();
  738. if (!skipSerializing && IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentOnSerializing, ref prevAttributeType))
  739. {
  740. onSerializing = onSerializing ?? new List<SerializationCallback>();
  741. onSerializing.Add(JsonContract.CreateSerializationCallback(method));
  742. currentOnSerializing = method;
  743. }
  744. if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentOnSerialized, ref prevAttributeType))
  745. {
  746. onSerialized = onSerialized ?? new List<SerializationCallback>();
  747. onSerialized.Add(JsonContract.CreateSerializationCallback(method));
  748. currentOnSerialized = method;
  749. }
  750. if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentOnDeserializing, ref prevAttributeType))
  751. {
  752. onDeserializing = onDeserializing ?? new List<SerializationCallback>();
  753. onDeserializing.Add(JsonContract.CreateSerializationCallback(method));
  754. currentOnDeserializing = method;
  755. }
  756. if (!skipDeserialized && IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentOnDeserialized, ref prevAttributeType))
  757. {
  758. onDeserialized = onDeserialized ?? new List<SerializationCallback>();
  759. onDeserialized.Add(JsonContract.CreateSerializationCallback(method));
  760. currentOnDeserialized = method;
  761. }
  762. if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentOnError, ref prevAttributeType))
  763. {
  764. onError = onError ?? new List<SerializationErrorCallback>();
  765. onError.Add(JsonContract.CreateSerializationErrorCallback(method));
  766. currentOnError = method;
  767. }
  768. }
  769. }
  770. }
  771. private static bool IsConcurrentOrObservableCollection(Type t)
  772. {
  773. if (t.IsGenericType())
  774. {
  775. Type definition = t.GetGenericTypeDefinition();
  776. switch (definition.FullName)
  777. {
  778. case "System.Collections.Concurrent.ConcurrentQueue`1":
  779. case "System.Collections.Concurrent.ConcurrentStack`1":
  780. case "System.Collections.Concurrent.ConcurrentBag`1":
  781. case JsonTypeReflector.ConcurrentDictionaryTypeName:
  782. case "System.Collections.ObjectModel.ObservableCollection`1":
  783. return true;
  784. }
  785. }
  786. return false;
  787. }
  788. private static bool ShouldSkipDeserialized(Type t)
  789. {
  790. // ConcurrentDictionary throws an error in its OnDeserialized so ignore - http://json.codeplex.com/discussions/257093
  791. if (IsConcurrentOrObservableCollection(t))
  792. {
  793. return true;
  794. }
  795. #if !NET20
  796. if (t.Name == FSharpUtils.FSharpSetTypeName || t.Name == FSharpUtils.FSharpMapTypeName)
  797. {
  798. return true;
  799. }
  800. #endif
  801. return false;
  802. }
  803. private static bool ShouldSkipSerializing(Type t)
  804. {
  805. if (IsConcurrentOrObservableCollection(t))
  806. {
  807. return true;
  808. }
  809. #if !NET20
  810. if (t.Name == FSharpUtils.FSharpSetTypeName || t.Name == FSharpUtils.FSharpMapTypeName)
  811. {
  812. return true;
  813. }
  814. #endif
  815. return false;
  816. }
  817. private List<Type> GetClassHierarchyForType(Type type)
  818. {
  819. List<Type> ret = new List<Type>();
  820. Type current = type;
  821. while (current != null && current != typeof(object))
  822. {
  823. ret.Add(current);
  824. current = current.BaseType();
  825. }
  826. // Return the class list in order of simple => complex
  827. ret.Reverse();
  828. return ret;
  829. }
  830. /// <summary>
  831. /// Creates a <see cref="JsonDictionaryContract"/> for the given type.
  832. /// </summary>
  833. /// <param name="objectType">Type of the object.</param>
  834. /// <returns>A <see cref="JsonDictionaryContract"/> for the given type.</returns>
  835. protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType)
  836. {
  837. JsonDictionaryContract contract = new JsonDictionaryContract(objectType);
  838. InitializeContract(contract);
  839. JsonContainerAttribute containerAttribute = JsonTypeReflector.GetAttribute<JsonContainerAttribute>(objectType);
  840. if (containerAttribute?.NamingStrategyType != null)
  841. {
  842. NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute);
  843. contract.DictionaryKeyResolver = s => namingStrategy.GetDictionaryKey(s);
  844. }
  845. else
  846. {
  847. contract.DictionaryKeyResolver = ResolveDictionaryKey;
  848. }
  849. ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType);
  850. if (overrideConstructor != null)
  851. {
  852. ParameterInfo[] parameters = overrideConstructor.GetParameters();
  853. Type expectedParameterType = (contract.DictionaryKeyType != null && contract.DictionaryValueType != null)
  854. ? typeof(IEnumerable<>).MakeGenericType(typeof(KeyValuePair<,>).MakeGenericType(contract.DictionaryKeyType, contract.DictionaryValueType))
  855. : typeof(IDictionary);
  856. if (parameters.Length == 0)
  857. {
  858. contract.HasParameterizedCreator = false;
  859. }
  860. else if (parameters.Length == 1 && expectedParameterType.IsAssignableFrom(parameters[0].ParameterType))
  861. {
  862. contract.HasParameterizedCreator = true;
  863. }
  864. else
  865. {
  866. throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, expectedParameterType));
  867. }
  868. contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor);
  869. }
  870. return contract;
  871. }
  872. /// <summary>
  873. /// Creates a <see cref="JsonArrayContract"/> for the given type.
  874. /// </summary>
  875. /// <param name="objectType">Type of the object.</param>
  876. /// <returns>A <see cref="JsonArrayContract"/> for the given type.</returns>
  877. protected virtual JsonArrayContract CreateArrayContract(Type objectType)
  878. {
  879. JsonArrayContract contract = new JsonArrayContract(objectType);
  880. InitializeContract(contract);
  881. ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType);
  882. if (overrideConstructor != null)
  883. {
  884. ParameterInfo[] parameters = overrideConstructor.GetParameters();
  885. Type expectedParameterType = (contract.CollectionItemType != null)
  886. ? typeof(IEnumerable<>).MakeGenericType(contract.CollectionItemType)
  887. : typeof(IEnumerable);
  888. if (parameters.Length == 0)
  889. {
  890. contract.HasParameterizedCreator = false;
  891. }
  892. else if (parameters.Length == 1 && expectedParameterType.IsAssignableFrom(parameters[0].ParameterType))
  893. {
  894. contract.HasParameterizedCreator = true;
  895. }
  896. else
  897. {
  898. throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, expectedParameterType));
  899. }
  900. contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor);
  901. }
  902. return contract;
  903. }
  904. /// <summary>
  905. /// Creates a <see cref="JsonPrimitiveContract"/> for the given type.
  906. /// </summary>
  907. /// <param name="objectType">Type of the object.</param>
  908. /// <returns>A <see cref="JsonPrimitiveContract"/> for the given type.</returns>
  909. protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType)
  910. {
  911. JsonPrimitiveContract contract = new JsonPrimitiveContract(objectType);
  912. InitializeContract(contract);
  913. return contract;
  914. }
  915. /// <summary>
  916. /// Creates a <see cref="JsonLinqContract"/> for the given type.
  917. /// </summary>
  918. /// <param name="objectType">Type of the object.</param>
  919. /// <returns>A <see cref="JsonLinqContract"/> for the given type.</returns>
  920. protected virtual JsonLinqContract CreateLinqContract(Type objectType)
  921. {
  922. JsonLinqContract contract = new JsonLinqContract(objectType);
  923. InitializeContract(contract);
  924. return contract;
  925. }
  926. #if HAVE_BINARY_SERIALIZATION
  927. /// <summary>
  928. /// Creates a <see cref="JsonISerializableContract"/> for the given type.
  929. /// </summary>
  930. /// <param name="objectType">Type of the object.</param>
  931. /// <returns>A <see cref="JsonISerializableContract"/> for the given type.</returns>
  932. protected virtual JsonISerializableContract CreateISerializableContract(Type objectType)
  933. {
  934. JsonISerializableContract contract = new JsonISerializableContract(objectType);
  935. InitializeContract(contract);
  936. ConstructorInfo constructorInfo = contract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(SerializationInfo), typeof(StreamingContext) }, null);
  937. if (constructorInfo != null)
  938. {
  939. ObjectConstructor<object> creator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructorInfo);
  940. contract.ISerializableCreator = creator;
  941. }
  942. return contract;
  943. }
  944. #endif
  945. #if !NET20
  946. /// <summary>
  947. /// Creates a <see cref="JsonDynamicContract"/> for the given type.
  948. /// </summary>
  949. /// <param name="objectType">Type of the object.</param>
  950. /// <returns>A <see cref="JsonDynamicContract"/> for the given type.</returns>
  951. protected virtual JsonDynamicContract CreateDynamicContract(Type objectType)
  952. {
  953. JsonDynamicContract contract = new JsonDynamicContract(objectType);
  954. InitializeContract(contract);
  955. JsonContainerAttribute containerAttribute = JsonTypeReflector.GetAttribute<JsonContainerAttribute>(objectType);
  956. if (containerAttribute?.NamingStrategyType != null)
  957. {
  958. NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute);
  959. contract.PropertyNameResolver = s => namingStrategy.GetDictionaryKey(s);
  960. }
  961. else
  962. {
  963. contract.PropertyNameResolver = ResolveDictionaryKey;
  964. }
  965. contract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut));
  966. return contract;
  967. }
  968. #endif
  969. /// <summary>
  970. /// Creates a <see cref="JsonStringContract"/> for the given type.
  971. /// </summary>
  972. /// <param name="objectType">Type of the object.</param>
  973. /// <returns>A <see cref="JsonStringContract"/> for the given type.</returns>
  974. protected virtual JsonStringContract CreateStringContract(Type objectType)
  975. {
  976. JsonStringContract contract = new JsonStringContract(objectType);
  977. InitializeContract(contract);
  978. return contract;
  979. }
  980. /// <summary>
  981. /// Determines which contract type is created for the given type.
  982. /// </summary>
  983. /// <param name="objectType">Type of the object.</param>
  984. /// <returns>A <see cref="JsonContract"/> for the given type.</returns>
  985. protected virtual JsonContract CreateContract(Type objectType)
  986. {
  987. if (IsJsonPrimitiveType(objectType))
  988. {
  989. return CreatePrimitiveContract(objectType);
  990. }
  991. Type t = ReflectionUtils.EnsureNotNullableType(objectType);
  992. JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(t);
  993. if (containerAttribute is JsonObjectAttribute)
  994. {
  995. return CreateObjectContract(objectType);
  996. }
  997. if (containerAttribute is JsonArrayAttribute)
  998. {
  999. return CreateArrayContract(objectType);
  1000. }
  1001. if (containerAttribute is JsonDictionaryAttribute)
  1002. {
  1003. return CreateDictionaryContract(objectType);
  1004. }
  1005. #if !NET20
  1006. // don't use GetDataContractAttribute because it looks for the attribute on base classes
  1007. DataContractAttribute dataContractAttribute = JsonTypeReflector.GetCachedAttribute<DataContractAttribute>(objectType);
  1008. if (dataContractAttribute != null)
  1009. {
  1010. return CreateObjectContract(objectType);
  1011. }
  1012. #endif
  1013. if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken)))
  1014. {
  1015. return CreateLinqContract(objectType);
  1016. }
  1017. if (CollectionUtils.IsDictionaryType(t))
  1018. {
  1019. return CreateDictionaryContract(objectType);
  1020. }
  1021. if (typeof(IEnumerable).IsAssignableFrom(t))
  1022. {
  1023. return CreateArrayContract(t);
  1024. }
  1025. if (CanConvertToString(t))
  1026. {
  1027. return CreateStringContract(objectType);
  1028. }
  1029. #if HAVE_BINARY_SERIALIZATION
  1030. if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t) && JsonTypeReflector.IsSerializable(t))
  1031. {
  1032. return CreateISerializableContract(objectType);
  1033. }
  1034. #endif
  1035. #if !NET20
  1036. if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t))
  1037. {
  1038. return CreateDynamicContract(objectType);
  1039. }
  1040. #endif
  1041. // tested last because it is not possible to automatically deserialize custom IConvertible types
  1042. if (IsIConvertible(t))
  1043. {
  1044. return CreatePrimitiveContract(t);
  1045. }
  1046. return CreateObjectContract(objectType);
  1047. }
  1048. internal static bool IsJsonPrimitiveType(Type t)
  1049. {
  1050. PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t);
  1051. return (typeCode != PrimitiveTypeCode.Empty && typeCode != PrimitiveTypeCode.Object);
  1052. }
  1053. internal static bool IsIConvertible(Type t)
  1054. {
  1055. if (typeof(IConvertible).IsAssignableFrom(t)
  1056. || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t))))
  1057. {
  1058. return !typeof(JToken).IsAssignableFrom(t);
  1059. }
  1060. return false;
  1061. }
  1062. internal static bool CanConvertToString(Type type)
  1063. {
  1064. if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out _))
  1065. {
  1066. return true;
  1067. }
  1068. if (type == typeof(Type) || type.IsSubclassOf(typeof(Type)))
  1069. {
  1070. return true;
  1071. }
  1072. return false;
  1073. }
  1074. private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType)
  1075. {
  1076. if (!method.IsDefined(attributeType, false))
  1077. {
  1078. return false;
  1079. }
  1080. if (currentCallback != null)
  1081. {
  1082. throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType));
  1083. }
  1084. if (prevAttributeType != null)
  1085. {
  1086. throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method));
  1087. }
  1088. if (method.IsVirtual)
  1089. {
  1090. throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType));
  1091. }
  1092. if (method.ReturnType != typeof(void))
  1093. {
  1094. throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method));
  1095. }
  1096. if (attributeType == typeof(OnErrorAttribute))
  1097. {
  1098. if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
  1099. {
  1100. 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)));
  1101. }
  1102. }
  1103. else
  1104. {
  1105. if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))
  1106. {
  1107. 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)));
  1108. }
  1109. }
  1110. prevAttributeType = attributeType;
  1111. return true;
  1112. }
  1113. internal static string GetClrTypeFullName(Type type)
  1114. {
  1115. if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters())
  1116. {
  1117. return type.FullName;
  1118. }
  1119. return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name);
  1120. }
  1121. /// <summary>
  1122. /// Creates properties for the given <see cref="JsonContract"/>.
  1123. /// </summary>
  1124. /// <param name="type">The type to create properties for.</param>
  1125. /// /// <param name="memberSerialization">The member serialization mode for the type.</param>
  1126. /// <returns>Properties for the given <see cref="JsonContract"/>.</returns>
  1127. protected virtual IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  1128. {
  1129. List<MemberInfo> members = GetSerializableMembers(type);
  1130. if (members == null)
  1131. {
  1132. throw new JsonSerializationException("Null collection of serializable members returned.");
  1133. }
  1134. PropertyNameTable nameTable = GetNameTable();
  1135. JsonPropertyCollection properties = new JsonPropertyCollection(type);
  1136. foreach (MemberInfo member in members)
  1137. {
  1138. JsonProperty property = CreateProperty(member, memberSerialization);
  1139. if (property != null)
  1140. {
  1141. // nametable is not thread-safe for multiple writers
  1142. lock (nameTable)
  1143. {
  1144. property.PropertyName = nameTable.Add(property.PropertyName);
  1145. }
  1146. properties.AddProperty(property);
  1147. }
  1148. }
  1149. IList<JsonProperty> orderedProperties = properties.OrderBy(p => p.Order ?? -1).List();
  1150. return orderedProperties;
  1151. }
  1152. internal virtual PropertyNameTable GetNameTable()
  1153. {
  1154. return _nameTable;
  1155. }
  1156. /// <summary>
  1157. /// Creates the <see cref="IValueProvider"/> used by the serializer to get and set values from a member.
  1158. /// </summary>
  1159. /// <param name="member">The member.</param>
  1160. /// <returns>The <see cref="IValueProvider"/> used by the serializer to get and set values from a member.</returns>
  1161. protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member)
  1162. {
  1163. // warning - this method use to cause errors with Intellitrace. Retest in VS Ultimate after changes
  1164. IValueProvider valueProvider;
  1165. #if NETFX
  1166. if (DynamicCodeGeneration) valueProvider = new DynamicValueProvider(member);
  1167. else valueProvider = new ReflectionValueProvider(member);
  1168. #else
  1169. valueProvider = new ExpressionValueProvider(member);
  1170. // valueProvider = new ReflectionValueProvider(member);
  1171. #endif
  1172. // #if !(PORTABLE40 || PORTABLE || DOTNET || NETSTD)
  1173. // if (DynamicCodeGeneration)
  1174. // {
  1175. // valueProvider = new DynamicValueProvider(member);
  1176. // }
  1177. // else
  1178. // {
  1179. // valueProvider = new ReflectionValueProvider(member);
  1180. // }
  1181. // #elif !(PORTABLE40)
  1182. // valueProvider = new ExpressionValueProvider(member);
  1183. // #else
  1184. // valueProvider = new ReflectionValueProvider(member);
  1185. // #endif
  1186. return valueProvider;
  1187. }
  1188. /// <summary>
  1189. /// Creates a <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.
  1190. /// </summary>
  1191. /// <param name="memberSerialization">The member's parent <see cref="MemberSerialization"/>.</param>
  1192. /// <param name="member">The member to create a <see cref="JsonProperty"/> for.</param>
  1193. /// <returns>A created <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.</returns>
  1194. protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
  1195. {
  1196. JsonProperty property = new JsonProperty();
  1197. property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
  1198. property.DeclaringType = member.DeclaringType;
  1199. property.ValueProvider = CreateMemberValueProvider(member);
  1200. property.AttributeProvider = new ReflectionAttributeProvider(member);
  1201. SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out bool allowNonPublicAccess);
  1202. if (memberSerialization != MemberSerialization.Fields)
  1203. {
  1204. property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
  1205. property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, property.HasMemberAttribute);
  1206. }
  1207. else
  1208. {
  1209. // write to readonly fields
  1210. property.Readable = true;
  1211. property.Writable = true;
  1212. }
  1213. if (!IgnoreShouldSerializeMembers)
  1214. {
  1215. property.ShouldSerialize = CreateShouldSerializeTest(member);
  1216. }
  1217. if (!IgnoreIsSpecifiedMembers)
  1218. {
  1219. SetIsSpecifiedActions(property, member, allowNonPublicAccess);
  1220. }
  1221. return property;
  1222. }
  1223. private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess)
  1224. {
  1225. #if !NET20
  1226. DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType);
  1227. MemberInfo memberInfo = attributeProvider as MemberInfo;
  1228. DataMemberAttribute dataMemberAttribute;
  1229. if (dataContractAttribute != null && memberInfo != null)
  1230. {
  1231. dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo)memberInfo);
  1232. }
  1233. else
  1234. {
  1235. dataMemberAttribute = null;
  1236. }
  1237. #endif
  1238. JsonPropertyAttribute propertyAttribute = JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(attributeProvider);
  1239. JsonRequiredAttribute requiredAttribute = JsonTypeReflector.GetAttribute<JsonRequiredAttribute>(attributeProvider);
  1240. string mappedName;
  1241. bool hasSpecifiedName;
  1242. if (propertyAttribute?.PropertyName != null)
  1243. {
  1244. mappedName = propertyAttribute.PropertyName;
  1245. hasSpecifiedName = true;
  1246. }
  1247. #if !NET20
  1248. else if (dataMemberAttribute?.Name != null)
  1249. {
  1250. mappedName = dataMemberAttribute.Name;
  1251. hasSpecifiedName = true;
  1252. }
  1253. #endif
  1254. else
  1255. {
  1256. mappedName = name;
  1257. hasSpecifiedName = false;
  1258. }
  1259. JsonContainerAttribute containerAttribute = JsonTypeReflector.GetAttribute<JsonContainerAttribute>(declaringType);
  1260. NamingStrategy namingStrategy;
  1261. if (propertyAttribute?.NamingStrategyType != null)
  1262. {
  1263. namingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(propertyAttribute.NamingStrategyType, propertyAttribute.NamingStrategyParameters);
  1264. }
  1265. else if (containerAttribute?.NamingStrategyType != null)
  1266. {
  1267. namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute);
  1268. }
  1269. else
  1270. {
  1271. namingStrategy = NamingStrategy;
  1272. }
  1273. if (namingStrategy != null)
  1274. {
  1275. property.PropertyName = namingStrategy.GetPropertyName(mappedName, hasSpecifiedName);
  1276. }
  1277. else
  1278. {
  1279. property.PropertyName = ResolvePropertyName(mappedName);
  1280. }
  1281. property.UnderlyingName = name;
  1282. bool hasMemberAttribute = false;
  1283. if (propertyAttribute != null)
  1284. {
  1285. property._required = propertyAttribute._required;
  1286. property.Order = propertyAttribute._order;
  1287. property.DefaultValueHandling = propertyAttribute._defaultValueHandling;
  1288. hasMemberAttribute = true;
  1289. property.NullValueHandling = propertyAttribute._nullValueHandling;
  1290. property.ReferenceLoopHandling = propertyAttribute._referenceLoopHandling;
  1291. property.ObjectCreationHandling = propertyAttribute._objectCreationHandling;
  1292. property.TypeNameHandling = propertyAttribute._typeNameHandling;
  1293. property.IsReference = propertyAttribute._isReference;
  1294. property.ItemIsReference = propertyAttribute._itemIsReference;
  1295. property.ItemConverter = propertyAttribute.ItemConverterType != null ? JsonTypeReflector.CreateJsonConverterInstance(propertyAttribute.ItemConverterType, propertyAttribute.ItemConverterParameters) : null;
  1296. property.ItemReferenceLoopHandling = propertyAttribute._itemReferenceLoopHandling;
  1297. property.ItemTypeNameHandling = propertyAttribute._itemTypeNameHandling;
  1298. }
  1299. else
  1300. {
  1301. property.NullValueHandling = null;
  1302. property.ReferenceLoopHandling = null;
  1303. property.ObjectCreationHandling = null;
  1304. property.TypeNameHandling = null;
  1305. property.IsReference = null;
  1306. property.ItemIsReference = null;
  1307. property.ItemConverter = null;
  1308. property.ItemReferenceLoopHandling = null;
  1309. property.ItemTypeNameHandling = null;
  1310. #if !NET20
  1311. if (dataMemberAttribute != null)
  1312. {
  1313. property._required = (dataMemberAttribute.IsRequired) ? Required.AllowNull : Required.Default;
  1314. property.Order = (dataMemberAttribute.Order != -1) ? (int?)dataMemberAttribute.Order : null;
  1315. property.DefaultValueHandling = (!dataMemberAttribute.EmitDefaultValue) ? (DefaultValueHandling?)DefaultValueHandling.Ignore : null;
  1316. hasMemberAttribute = true;
  1317. }
  1318. #endif
  1319. }
  1320. if (requiredAttribute != null)
  1321. {
  1322. property._required = Required.Always;
  1323. hasMemberAttribute = true;
  1324. }
  1325. property.HasMemberAttribute = hasMemberAttribute;
  1326. bool hasJsonIgnoreAttribute =
  1327. JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null
  1328. // automatically ignore extension data dictionary property if it is public
  1329. || JsonTypeReflector.GetAttribute<JsonExtensionDataAttribute>(attributeProvider) != null
  1330. || JsonTypeReflector.IsNonSerializable(attributeProvider)
  1331. ;
  1332. if (memberSerialization != MemberSerialization.OptIn)
  1333. {
  1334. bool hasIgnoreDataMemberAttribute = false;
  1335. #if !NET20
  1336. hasIgnoreDataMemberAttribute = (JsonTypeReflector.GetAttribute<IgnoreDataMemberAttribute>(attributeProvider) != null);
  1337. #endif
  1338. // ignored if it has JsonIgnore or NonSerialized or IgnoreDataMember attributes
  1339. property.Ignored = (hasJsonIgnoreAttribute || hasIgnoreDataMemberAttribute);
  1340. }
  1341. else
  1342. {
  1343. // ignored if it has JsonIgnore/NonSerialized or does not have DataMember or JsonProperty attributes
  1344. property.Ignored = (hasJsonIgnoreAttribute || !hasMemberAttribute);
  1345. }
  1346. // resolve converter for property
  1347. // the class type might have a converter but the property converter takes precedence
  1348. property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider);
  1349. DefaultValueAttribute defaultValueAttribute = JsonTypeReflector.GetAttribute<DefaultValueAttribute>(attributeProvider);
  1350. if (defaultValueAttribute != null)
  1351. {
  1352. property.DefaultValue = defaultValueAttribute.Value;
  1353. }
  1354. allowNonPublicAccess = false;
  1355. #pragma warning disable 618
  1356. if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic)
  1357. {
  1358. allowNonPublicAccess = true;
  1359. }
  1360. #pragma warning restore 618
  1361. if (hasMemberAttribute)
  1362. {
  1363. allowNonPublicAccess = true;
  1364. }
  1365. if (memberSerialization == MemberSerialization.Fields)
  1366. {
  1367. allowNonPublicAccess = true;
  1368. }
  1369. }
  1370. private Predicate<object> CreateShouldSerializeTest(MemberInfo member)
  1371. {
  1372. MethodInfo shouldSerializeMethod = member.DeclaringType.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes);
  1373. if (shouldSerializeMethod == null || shouldSerializeMethod.ReturnType != typeof(bool))
  1374. {
  1375. return null;
  1376. }
  1377. MethodCall<object, object> shouldSerializeCall =
  1378. JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(shouldSerializeMethod);
  1379. return o => (bool)shouldSerializeCall(o);
  1380. }
  1381. private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess)
  1382. {
  1383. MemberInfo specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  1384. if (specifiedMember == null)
  1385. {
  1386. specifiedMember = member.DeclaringType.GetField(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  1387. }
  1388. if (specifiedMember == null || ReflectionUtils.GetMemberUnderlyingType(specifiedMember) != typeof(bool))
  1389. {
  1390. return;
  1391. }
  1392. Func<object, object> specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(specifiedMember);
  1393. property.GetIsSpecified = o => (bool)specifiedPropertyGet(o);
  1394. if (ReflectionUtils.CanSetMemberValue(specifiedMember, allowNonPublicAccess, false))
  1395. {
  1396. property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(specifiedMember);
  1397. }
  1398. }
  1399. /// <summary>
  1400. /// Resolves the name of the property.
  1401. /// </summary>
  1402. /// <param name="propertyName">Name of the property.</param>
  1403. /// <returns>Resolved name of the property.</returns>
  1404. protected virtual string ResolvePropertyName(string propertyName)
  1405. {
  1406. if (NamingStrategy != null)
  1407. {
  1408. return NamingStrategy.GetPropertyName(propertyName, false);
  1409. }
  1410. return propertyName;
  1411. }
  1412. /// <summary>
  1413. /// Resolves the name of the extension data. By default no changes are made to extension data names.
  1414. /// </summary>
  1415. /// <param name="extensionDataName">Name of the extension data.</param>
  1416. /// <returns>Resolved name of the extension data.</returns>
  1417. protected virtual string ResolveExtensionDataName(string extensionDataName)
  1418. {
  1419. if (NamingStrategy != null)
  1420. {
  1421. return NamingStrategy.GetExtensionDataName(extensionDataName);
  1422. }
  1423. return extensionDataName;
  1424. }
  1425. /// <summary>
  1426. /// Resolves the key of the dictionary. By default <see cref="ResolvePropertyName"/> is used to resolve dictionary keys.
  1427. /// </summary>
  1428. /// <param name="dictionaryKey">Key of the dictionary.</param>
  1429. /// <returns>Resolved key of the dictionary.</returns>
  1430. protected virtual string ResolveDictionaryKey(string dictionaryKey)
  1431. {
  1432. if (NamingStrategy != null)
  1433. {
  1434. return NamingStrategy.GetDictionaryKey(dictionaryKey);
  1435. }
  1436. return ResolvePropertyName(dictionaryKey);
  1437. }
  1438. /// <summary>
  1439. /// Gets the resolved name of the property.
  1440. /// </summary>
  1441. /// <param name="propertyName">Name of the property.</param>
  1442. /// <returns>Name of the property.</returns>
  1443. public string GetResolvedPropertyName(string propertyName)
  1444. {
  1445. // this is a new method rather than changing the visibility of ResolvePropertyName to avoid
  1446. // a breaking change for anyone who has overidden the method
  1447. return ResolvePropertyName(propertyName);
  1448. }
  1449. }
  1450. }