JsonClassDataContract.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //----------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //----------------------------------------------------------------
  4. namespace System.Runtime.Serialization.Json
  5. {
  6. using System.Threading;
  7. using System.Xml;
  8. using System.Diagnostics;
  9. using System.ServiceModel;
  10. using System.Collections.Generic;
  11. using System.Security;
  12. class JsonClassDataContract : JsonDataContract
  13. {
  14. [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization."
  15. + "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
  16. [SecurityCritical]
  17. JsonClassDataContractCriticalHelper helper;
  18. [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
  19. Safe = "Doesn't leak anything.")]
  20. [SecuritySafeCritical]
  21. public JsonClassDataContract(ClassDataContract traditionalDataContract)
  22. : base(new JsonClassDataContractCriticalHelper(traditionalDataContract))
  23. {
  24. this.helper = base.Helper as JsonClassDataContractCriticalHelper;
  25. }
  26. internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate
  27. {
  28. [Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatReaderDelegate property.",
  29. Safe = "JsonFormatReaderDelegate only needs to be protected for write.")]
  30. [SecuritySafeCritical]
  31. get
  32. {
  33. if (helper.JsonFormatReaderDelegate == null)
  34. {
  35. lock (this)
  36. {
  37. if (helper.JsonFormatReaderDelegate == null)
  38. {
  39. if (TraditionalClassDataContract.IsReadOnlyContract)
  40. {
  41. DataContract.ThrowInvalidDataContractException(TraditionalClassDataContract.DeserializationExceptionMessage, null /*type*/);
  42. }
  43. JsonFormatClassReaderDelegate tempDelegate = new JsonFormatReaderGenerator().GenerateClassReader(TraditionalClassDataContract);
  44. Thread.MemoryBarrier();
  45. helper.JsonFormatReaderDelegate = tempDelegate;
  46. }
  47. }
  48. }
  49. return helper.JsonFormatReaderDelegate;
  50. }
  51. }
  52. internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate
  53. {
  54. [Fx.Tag.SecurityNote(Critical = "Fetches the critical JsonFormatWriterDelegate property.",
  55. Safe = "JsonFormatWriterDelegate only needs to be protected for write.")]
  56. [SecuritySafeCritical]
  57. get
  58. {
  59. if (helper.JsonFormatWriterDelegate == null)
  60. {
  61. lock (this)
  62. {
  63. if (helper.JsonFormatWriterDelegate == null)
  64. {
  65. JsonFormatClassWriterDelegate tempDelegate = new JsonFormatWriterGenerator().GenerateClassWriter(TraditionalClassDataContract);
  66. Thread.MemoryBarrier();
  67. helper.JsonFormatWriterDelegate = tempDelegate;
  68. }
  69. }
  70. }
  71. return helper.JsonFormatWriterDelegate;
  72. }
  73. }
  74. internal XmlDictionaryString[] MemberNames
  75. {
  76. [Fx.Tag.SecurityNote(Critical = "Fetches the critical MemberNames property.",
  77. Safe = "MemberNames only needs to be protected for write.")]
  78. [SecuritySafeCritical]
  79. get { return this.helper.MemberNames; }
  80. }
  81. internal override string TypeName
  82. {
  83. [Fx.Tag.SecurityNote(Critical = "Fetches the critical TypeName property.",
  84. Safe = "TypeName only needs to be protected for write.")]
  85. [SecuritySafeCritical]
  86. get { return this.helper.TypeName; }
  87. }
  88. ClassDataContract TraditionalClassDataContract
  89. {
  90. [Fx.Tag.SecurityNote(Critical = "Fetches the critical TraditionalClassDataContract property.",
  91. Safe = "TraditionalClassDataContract only needs to be protected for write.")]
  92. [SecuritySafeCritical]
  93. get { return this.helper.TraditionalClassDataContract; }
  94. }
  95. public override object ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
  96. {
  97. jsonReader.Read();
  98. object o = JsonFormatReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, MemberNames);
  99. jsonReader.ReadEndElement();
  100. return o;
  101. }
  102. public override void WriteJsonValueCore(XmlWriterDelegator jsonWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle)
  103. {
  104. jsonWriter.WriteAttributeString(null, JsonGlobals.typeString, null, JsonGlobals.objectString);
  105. JsonFormatWriterDelegate(jsonWriter, obj, context, TraditionalClassDataContract, MemberNames);
  106. }
  107. [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing types."
  108. + "Since the data is cached statically, we lock down access to it.")]
  109. #if !NO_SECURITY_ATTRIBUTES
  110. #pragma warning disable 618 // have not moved to the v4 security model yet
  111. [SecurityCritical(SecurityCriticalScope.Everything)]
  112. #pragma warning restore 618
  113. #endif
  114. class JsonClassDataContractCriticalHelper : JsonDataContractCriticalHelper
  115. {
  116. JsonFormatClassReaderDelegate jsonFormatReaderDelegate;
  117. JsonFormatClassWriterDelegate jsonFormatWriterDelegate;
  118. XmlDictionaryString[] memberNames;
  119. ClassDataContract traditionalClassDataContract;
  120. string typeName;
  121. public JsonClassDataContractCriticalHelper(ClassDataContract traditionalDataContract)
  122. : base(traditionalDataContract)
  123. {
  124. this.typeName = string.IsNullOrEmpty(traditionalDataContract.Namespace.Value) ? traditionalDataContract.Name.Value : string.Concat(traditionalDataContract.Name.Value, JsonGlobals.NameValueSeparatorString, XmlObjectSerializerWriteContextComplexJson.TruncateDefaultDataContractNamespace(traditionalDataContract.Namespace.Value));
  125. this.traditionalClassDataContract = traditionalDataContract;
  126. CopyMembersAndCheckDuplicateNames();
  127. }
  128. internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate
  129. {
  130. get { return this.jsonFormatReaderDelegate; }
  131. set { this.jsonFormatReaderDelegate = value; }
  132. }
  133. internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate
  134. {
  135. get { return this.jsonFormatWriterDelegate; }
  136. set { this.jsonFormatWriterDelegate = value; }
  137. }
  138. internal XmlDictionaryString[] MemberNames
  139. {
  140. get { return this.memberNames; }
  141. }
  142. internal ClassDataContract TraditionalClassDataContract
  143. {
  144. get { return this.traditionalClassDataContract; }
  145. }
  146. void CopyMembersAndCheckDuplicateNames()
  147. {
  148. if (traditionalClassDataContract.MemberNames != null)
  149. {
  150. int memberCount = traditionalClassDataContract.MemberNames.Length;
  151. Dictionary<string, object> memberTable = new Dictionary<string, object>(memberCount);
  152. XmlDictionaryString[] decodedMemberNames = new XmlDictionaryString[memberCount];
  153. for (int i = 0; i < memberCount; i++)
  154. {
  155. if (memberTable.ContainsKey(traditionalClassDataContract.MemberNames[i].Value))
  156. {
  157. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.JsonDuplicateMemberNames,
  158. DataContract.GetClrTypeFullName(traditionalClassDataContract.UnderlyingType), traditionalClassDataContract.MemberNames[i].Value)));
  159. }
  160. else
  161. {
  162. memberTable.Add(traditionalClassDataContract.MemberNames[i].Value, null);
  163. decodedMemberNames[i] = DataContractJsonSerializer.ConvertXmlNameToJsonName(traditionalClassDataContract.MemberNames[i]);
  164. }
  165. }
  166. this.memberNames = decodedMemberNames;
  167. }
  168. }
  169. }
  170. }
  171. }