PageRenderTime 60ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/JsonDotNetUnity/Scripts/JsonNetUnity/Serialization/JsonSerializerInternalWriter.cs

https://gitlab.com/sheetanshusrivastava3/Unity3D-code-repository-design-patterns
C# | 626 lines | 495 code | 103 blank | 28 comment | 134 complexity | 891a44af2388e3327fbef0f8485a4345 MD5 | raw file
  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. using System.Collections.Generic;
  28. using System.ComponentModel;
  29. using System.Globalization;
  30. using System.Linq;
  31. using System.Reflection;
  32. using System.Runtime.Serialization.Formatters;
  33. using Newtonsoft.Json.Linq;
  34. using Newtonsoft.Json.Utilities;
  35. using System.Runtime.Serialization;
  36. using System.Security;
  37. using UnityEngine;
  38. namespace Newtonsoft.Json.Serialization
  39. {
  40. internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
  41. {
  42. private JsonSerializerProxy _internalSerializer;
  43. private List<object> _serializeStack;
  44. private List<object> SerializeStack
  45. {
  46. get
  47. {
  48. if (_serializeStack == null)
  49. _serializeStack = new List<object>();
  50. return _serializeStack;
  51. }
  52. }
  53. public JsonSerializerInternalWriter(JsonSerializer serializer)
  54. : base(serializer)
  55. {
  56. }
  57. public void Serialize(JsonWriter jsonWriter, object value)
  58. {
  59. if (jsonWriter == null)
  60. throw new ArgumentNullException("jsonWriter");
  61. SerializeValue(jsonWriter, value, GetContractSafe(value), null, null);
  62. }
  63. private JsonSerializerProxy GetInternalSerializer()
  64. {
  65. if (_internalSerializer == null)
  66. _internalSerializer = new JsonSerializerProxy(this);
  67. return _internalSerializer;
  68. }
  69. private JsonContract GetContractSafe(object value)
  70. {
  71. if (value == null)
  72. return null;
  73. return Serializer.ContractResolver.ResolveContract(value.GetType());
  74. }
  75. private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContract collectionValueContract)
  76. {
  77. if (contract.UnderlyingType == typeof (byte[]))
  78. {
  79. bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract);
  80. if (includeTypeDetails)
  81. {
  82. writer.WriteStartObject();
  83. WriteTypeProperty(writer, contract.CreatedType);
  84. writer.WritePropertyName(JsonTypeReflector.ValuePropertyName);
  85. writer.WriteValue(value);
  86. writer.WriteEndObject();
  87. return;
  88. }
  89. }
  90. writer.WriteValue(value);
  91. }
  92. private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
  93. {
  94. JsonConverter converter = (member != null) ? member.Converter : null;
  95. if (value == null)
  96. {
  97. writer.WriteNull();
  98. return;
  99. }
  100. if ((converter != null
  101. || ((converter = valueContract.Converter) != null)
  102. || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
  103. || ((converter = valueContract.InternalConverter) != null))
  104. && converter.CanWrite)
  105. {
  106. SerializeConvertable(writer, converter, value, valueContract);
  107. }
  108. else if (valueContract is JsonPrimitiveContract)
  109. {
  110. SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, collectionValueContract);
  111. }
  112. else if (valueContract is JsonStringContract)
  113. {
  114. SerializeString(writer, value, (JsonStringContract) valueContract);
  115. }
  116. else if (valueContract is JsonObjectContract)
  117. {
  118. SerializeObject(writer, value, (JsonObjectContract)valueContract, member, collectionValueContract);
  119. }
  120. else if (valueContract is JsonDictionaryContract)
  121. {
  122. JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
  123. SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
  124. }
  125. else if (valueContract is JsonArrayContract)
  126. {
  127. JsonArrayContract arrayContract = (JsonArrayContract) valueContract;
  128. SerializeList(writer, arrayContract.CreateWrapper(value), arrayContract, member, collectionValueContract);
  129. }
  130. else if (valueContract is JsonLinqContract)
  131. {
  132. ((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
  133. }
  134. #if !(NETFX_CORE || UNITY_WP8)
  135. else if (valueContract is JsonISerializableContract)
  136. {
  137. SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract);
  138. }
  139. #endif
  140. }
  141. private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
  142. {
  143. if (value == null)
  144. return false;
  145. if (contract is JsonPrimitiveContract)
  146. return false;
  147. bool? isReference = null;
  148. // value could be coming from a dictionary or array and not have a property
  149. if (property != null)
  150. isReference = property.IsReference;
  151. if (isReference == null)
  152. isReference = contract.IsReference;
  153. if (isReference == null)
  154. {
  155. if (contract is JsonArrayContract)
  156. isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
  157. else
  158. isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
  159. }
  160. if (!isReference.Value)
  161. return false;
  162. return Serializer.ReferenceResolver.IsReferenced(this, value);
  163. }
  164. private void WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract)
  165. {
  166. string propertyName = property.PropertyName;
  167. object defaultValue = property.DefaultValue;
  168. if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
  169. memberValue == null)
  170. return;
  171. if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore)
  172. && MiscellaneousUtils.ValueEquals(memberValue, defaultValue))
  173. return;
  174. if (ShouldWriteReference(memberValue, property, contract))
  175. {
  176. writer.WritePropertyName(propertyName);
  177. WriteReference(writer, memberValue);
  178. return;
  179. }
  180. if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling, contract))
  181. return;
  182. if (memberValue == null && property.Required == Required.Always)
  183. throw new JsonSerializationException("Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
  184. writer.WritePropertyName(propertyName);
  185. SerializeValue(writer, memberValue, contract, property, null);
  186. }
  187. private bool CheckForCircularReference(object value, ReferenceLoopHandling? referenceLoopHandling, JsonContract contract)
  188. {
  189. if (value == null || contract is JsonPrimitiveContract)
  190. return true;
  191. if (SerializeStack.IndexOf(value) != -1)
  192. {
  193. var selfRef = (value is Vector2 || value is Vector3 || value is Vector4 || value is Color || value is Color32)
  194. ? ReferenceLoopHandling.Ignore
  195. : referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling);
  196. switch (selfRef)
  197. {
  198. case ReferenceLoopHandling.Error:
  199. throw new JsonSerializationException("Self referencing loop detected for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
  200. case ReferenceLoopHandling.Ignore:
  201. return false;
  202. case ReferenceLoopHandling.Serialize:
  203. return true;
  204. default:
  205. throw new InvalidOperationException("Unexpected ReferenceLoopHandling value: '{0}'".FormatWith(CultureInfo.InvariantCulture, Serializer.ReferenceLoopHandling));
  206. }
  207. }
  208. return true;
  209. }
  210. private void WriteReference(JsonWriter writer, object value)
  211. {
  212. writer.WriteStartObject();
  213. writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
  214. writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value));
  215. writer.WriteEndObject();
  216. }
  217. internal static bool TryConvertToString(object value, Type type, out string s)
  218. {
  219. #if !UNITY_WP8
  220. TypeConverter converter = ConvertUtils.GetConverter(type);
  221. // use the objectType's TypeConverter if it has one and can convert to a string
  222. if (converter != null
  223. #if !UNITY_WP8
  224. && !(converter is ComponentConverter)
  225. #endif
  226. && converter.GetType() != typeof(TypeConverter))
  227. {
  228. if (converter.CanConvertTo(typeof(string)))
  229. {
  230. #if !UNITY_WP8
  231. s = converter.ConvertToInvariantString(value);
  232. #else
  233. s = converter.ConvertToString(value);
  234. #endif
  235. return true;
  236. }
  237. }
  238. #endif
  239. #if UNITY_WP8
  240. if (value is Guid || value is Uri || value is TimeSpan)
  241. {
  242. s = value.ToString();
  243. return true;
  244. }
  245. #endif
  246. if (value is Type)
  247. {
  248. s = ((Type)value).AssemblyQualifiedName;
  249. return true;
  250. }
  251. s = null;
  252. return false;
  253. }
  254. private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
  255. {
  256. contract.InvokeOnSerializing(value, Serializer.Context);
  257. string s;
  258. TryConvertToString(value, contract.UnderlyingType, out s);
  259. writer.WriteValue(s);
  260. contract.InvokeOnSerialized(value, Serializer.Context);
  261. }
  262. private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContract collectionValueContract)
  263. {
  264. contract.InvokeOnSerializing(value, Serializer.Context);
  265. SerializeStack.Add(value);
  266. writer.WriteStartObject();
  267. bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
  268. if (isReference)
  269. {
  270. writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
  271. writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, value));
  272. }
  273. if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
  274. {
  275. WriteTypeProperty(writer, contract.UnderlyingType);
  276. }
  277. int initialDepth = writer.Top;
  278. foreach (JsonProperty property in contract.Properties)
  279. {
  280. try
  281. {
  282. if (!property.Ignored && property.Readable && ShouldSerialize(property, value) && IsSpecified(property, value))
  283. {
  284. object memberValue = property.ValueProvider.GetValue(value);
  285. JsonContract memberContract = GetContractSafe(memberValue);
  286. WriteMemberInfoProperty(writer, memberValue, property, memberContract);
  287. }
  288. }
  289. catch (Exception ex)
  290. {
  291. if (IsErrorHandled(value, contract, property.PropertyName, ex))
  292. HandleError(writer, initialDepth);
  293. else
  294. throw;
  295. }
  296. }
  297. writer.WriteEndObject();
  298. SerializeStack.RemoveAt(SerializeStack.Count - 1);
  299. contract.InvokeOnSerialized(value, Serializer.Context);
  300. }
  301. private void WriteTypeProperty(JsonWriter writer, Type type)
  302. {
  303. writer.WritePropertyName(JsonTypeReflector.TypePropertyName);
  304. writer.WriteValue(ReflectionUtils.GetTypeName(type, Serializer.TypeNameAssemblyFormat, Serializer.Binder));
  305. }
  306. private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
  307. {
  308. return ((value & flag) == flag);
  309. }
  310. private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
  311. {
  312. return ((value & flag) == flag);
  313. }
  314. private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
  315. {
  316. return ((value & flag) == flag);
  317. }
  318. private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract)
  319. {
  320. if (ShouldWriteReference(value, null, contract))
  321. {
  322. WriteReference(writer, value);
  323. }
  324. else
  325. {
  326. if (!CheckForCircularReference(value, null, contract))
  327. return;
  328. SerializeStack.Add(value);
  329. converter.WriteJson(writer, value, GetInternalSerializer());
  330. SerializeStack.RemoveAt(SerializeStack.Count - 1);
  331. }
  332. }
  333. private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
  334. {
  335. contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context);
  336. SerializeStack.Add(values.UnderlyingCollection);
  337. bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
  338. bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract);
  339. if (isReference || includeTypeDetails)
  340. {
  341. writer.WriteStartObject();
  342. if (isReference)
  343. {
  344. writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
  345. writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingCollection));
  346. }
  347. if (includeTypeDetails)
  348. {
  349. WriteTypeProperty(writer, values.UnderlyingCollection.GetType());
  350. }
  351. writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
  352. }
  353. JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));
  354. writer.WriteStartArray();
  355. int initialDepth = writer.Top;
  356. int index = 0;
  357. // note that an error in the IEnumerable won't be caught
  358. foreach (object value in values)
  359. {
  360. try
  361. {
  362. JsonContract valueContract = GetContractSafe(value);
  363. if (ShouldWriteReference(value, null, valueContract))
  364. {
  365. WriteReference(writer, value);
  366. }
  367. else
  368. {
  369. if (CheckForCircularReference(value, null, contract))
  370. {
  371. SerializeValue(writer, value, valueContract, null, childValuesContract);
  372. }
  373. }
  374. }
  375. catch (Exception ex)
  376. {
  377. if (IsErrorHandled(values.UnderlyingCollection, contract, index, ex))
  378. HandleError(writer, initialDepth);
  379. else
  380. throw;
  381. }
  382. finally
  383. {
  384. index++;
  385. }
  386. }
  387. writer.WriteEndArray();
  388. if (isReference || includeTypeDetails)
  389. {
  390. writer.WriteEndObject();
  391. }
  392. SerializeStack.RemoveAt(SerializeStack.Count - 1);
  393. contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context);
  394. }
  395. #if !(NETFX_CORE || UNITY_WP8)
  396. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Security.SecuritySafeCriticalAttribute")]
  397. [SecuritySafeCritical]
  398. private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract)
  399. {
  400. contract.InvokeOnSerializing(value, Serializer.Context);
  401. SerializeStack.Add(value);
  402. writer.WriteStartObject();
  403. SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
  404. value.GetObjectData(serializationInfo, Serializer.Context);
  405. foreach (SerializationEntry serializationEntry in serializationInfo)
  406. {
  407. writer.WritePropertyName(serializationEntry.Name);
  408. SerializeValue(writer, serializationEntry.Value, GetContractSafe(serializationEntry.Value), null, null);
  409. }
  410. writer.WriteEndObject();
  411. SerializeStack.RemoveAt(SerializeStack.Count - 1);
  412. contract.InvokeOnSerialized(value, Serializer.Context);
  413. }
  414. #endif
  415. private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
  416. {
  417. if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeNameHandlingFlag))
  418. return true;
  419. if (member != null)
  420. {
  421. if ((member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto
  422. // instance and property type are different
  423. && contract.UnderlyingType != member.PropertyType)
  424. {
  425. JsonContract memberTypeContract = Serializer.ContractResolver.ResolveContract(member.PropertyType);
  426. // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default)
  427. if (contract.UnderlyingType != memberTypeContract.CreatedType)
  428. return true;
  429. }
  430. }
  431. else if (collectionValueContract != null)
  432. {
  433. if (Serializer.TypeNameHandling == TypeNameHandling.Auto && contract.UnderlyingType != collectionValueContract.UnderlyingType)
  434. return true;
  435. }
  436. return false;
  437. }
  438. private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContract collectionValueContract)
  439. {
  440. contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);
  441. SerializeStack.Add(values.UnderlyingDictionary);
  442. writer.WriteStartObject();
  443. bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
  444. if (isReference)
  445. {
  446. writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
  447. writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingDictionary));
  448. }
  449. if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
  450. {
  451. WriteTypeProperty(writer, values.UnderlyingDictionary.GetType());
  452. }
  453. JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
  454. int initialDepth = writer.Top;
  455. // Mono Unity 3.0 fix
  456. IDictionary d = values;
  457. foreach (DictionaryEntry entry in d)
  458. {
  459. string propertyName = GetPropertyName(entry);
  460. propertyName = (contract.PropertyNameResolver != null)
  461. ? contract.PropertyNameResolver(propertyName)
  462. : propertyName;
  463. try
  464. {
  465. object value = entry.Value;
  466. JsonContract valueContract = GetContractSafe(value);
  467. if (ShouldWriteReference(value, null, valueContract))
  468. {
  469. writer.WritePropertyName(propertyName);
  470. WriteReference(writer, value);
  471. }
  472. else
  473. {
  474. if (!CheckForCircularReference(value, null, contract))
  475. continue;
  476. writer.WritePropertyName(propertyName);
  477. SerializeValue(writer, value, valueContract, null, childValuesContract);
  478. }
  479. }
  480. catch (Exception ex)
  481. {
  482. if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, ex))
  483. HandleError(writer, initialDepth);
  484. else
  485. throw;
  486. }
  487. }
  488. writer.WriteEndObject();
  489. SerializeStack.RemoveAt(SerializeStack.Count - 1);
  490. contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context);
  491. }
  492. private string GetPropertyName(DictionaryEntry entry)
  493. {
  494. string propertyName;
  495. if (entry.Key is IConvertible)
  496. return Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
  497. else if (TryConvertToString(entry.Key, entry.Key.GetType(), out propertyName))
  498. return propertyName;
  499. else
  500. return entry.Key.ToString();
  501. }
  502. private void HandleError(JsonWriter writer, int initialDepth)
  503. {
  504. ClearErrorContext();
  505. while (writer.Top > initialDepth)
  506. {
  507. writer.WriteEnd();
  508. }
  509. }
  510. private bool ShouldSerialize(JsonProperty property, object target)
  511. {
  512. if (property.ShouldSerialize == null)
  513. return true;
  514. return property.ShouldSerialize(target);
  515. }
  516. private bool IsSpecified(JsonProperty property, object target)
  517. {
  518. if (property.GetIsSpecified == null)
  519. return true;
  520. return property.GetIsSpecified(target);
  521. }
  522. }
  523. }