1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Runtime.Serialization.Json
8 using System.Collections.Generic;
10 using System.Security;
12 using System.ServiceModel;
18 public class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
20 class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
23 string extensionDataValueType;
24 DateTimeFormat dateTimeFormat;
25 bool useSimpleDictionaryFormat;
27 public XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
28 : base(serializer, serializer.MaxItemsInObjectGraph,
29 new StreamingContext(StreamingContextStates.All),
30 serializer.IgnoreExtensionDataObject)
32 this.rootTypeDataContract = rootTypeDataContract;
33 this.serializerKnownTypeList = serializer.knownTypeList;
34 this.dataContractSurrogate = serializer.DataContractSurrogate;
35 this.dateTimeFormat = serializer.DateTimeFormat;
36 this.useSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat;
39 internal IList<Type> SerializerKnownTypeList
43 return this.serializerKnownTypeList;
47 public bool UseSimpleDictionaryFormat
51 return this.useSimpleDictionaryFormat;
55 protected override void StartReadExtensionDataValue(XmlReaderDelegator xmlReader)
57 extensionDataValueType = xmlReader.GetAttribute(JsonGlobals.typeString);
60 protected override IDataNode ReadPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
64 switch (extensionDataValueType)
67 case JsonGlobals.stringString:
68 dataNode = new DataNode<string>(xmlReader.ReadContentAsString());
70 case JsonGlobals.booleanString:
71 dataNode = new DataNode<bool>(xmlReader.ReadContentAsBoolean());
73 case JsonGlobals.numberString:
74 dataNode = ReadNumericalPrimitiveExtensionDataValue(xmlReader);
77 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
78 XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonUnexpectedAttributeValue, extensionDataValueType)));
81 xmlReader.ReadEndElement();
85 IDataNode ReadNumericalPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader)
88 object numericalValue = JsonObjectDataContract.ParseJsonNumber(xmlReader.ReadContentAsString(), out type);
92 return new DataNode<byte>((byte)numericalValue);
94 return new DataNode<sbyte>((sbyte)numericalValue);
96 return new DataNode<short>((short)numericalValue);
98 return new DataNode<int>((int)numericalValue);
100 return new DataNode<long>((long)numericalValue);
101 case TypeCode.UInt16:
102 return new DataNode<ushort>((ushort)numericalValue);
103 case TypeCode.UInt32:
104 return new DataNode<uint>((uint)numericalValue);
105 case TypeCode.UInt64:
106 return new DataNode<ulong>((ulong)numericalValue);
107 case TypeCode.Single:
108 return new DataNode<float>((float)numericalValue);
109 case TypeCode.Double:
110 return new DataNode<double>((double)numericalValue);
111 case TypeCode.Decimal:
112 return new DataNode<decimal>((decimal)numericalValue);
114 throw Fx.AssertAndThrow("JsonObjectDataContract.ParseJsonNumber shouldn't return a TypeCode that we're not expecting");
118 internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
120 return new XmlObjectSerializerReadContextComplexJson(serializer, rootTypeDataContract);
124 public override int GetArraySize()
126 internal override int GetArraySize()
132 protected override object ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
134 return DataContractJsonSerializer.ReadJsonValue(dataContract, reader, this);
138 public override void ReadAttributes(XmlReaderDelegator xmlReader)
140 internal override void ReadAttributes(XmlReaderDelegator xmlReader)
143 if (attributes == null)
144 attributes = new Attributes();
147 if (xmlReader.MoveToAttribute(JsonGlobals.typeString) && xmlReader.Value == JsonGlobals.nullString)
149 attributes.XsiNil = true;
151 else if (xmlReader.MoveToAttribute(JsonGlobals.serverTypeString))
153 XmlQualifiedName qualifiedTypeName = JsonReaderDelegator.ParseQualifiedName(xmlReader.Value);
154 attributes.XsiTypeName = qualifiedTypeName.Name;
156 string serverTypeNamespace = qualifiedTypeName.Namespace;
158 if (!string.IsNullOrEmpty(serverTypeNamespace))
160 switch (serverTypeNamespace[0])
163 serverTypeNamespace = string.Concat(Globals.DataContractXsdBaseNamespace, serverTypeNamespace.Substring(1));
166 if (serverTypeNamespace.Length >= 2)
168 switch (serverTypeNamespace[1])
172 serverTypeNamespace = serverTypeNamespace.Substring(1);
184 attributes.XsiTypeNamespace = serverTypeNamespace;
186 xmlReader.MoveToElement();
189 public int GetJsonMemberIndex(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, int memberIndex, ExtensionDataObject extensionData)
191 int length = memberNames.Length;
194 for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
196 if (xmlReader.IsStartElement(memberNames[index], XmlDictionaryString.Empty))
202 if (TryGetJsonLocalName(xmlReader, out name))
204 for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
206 if (memberNames[index].Value == name)
213 HandleMemberNotFound(xmlReader, extensionData, memberIndex);
217 internal static bool TryGetJsonLocalName(XmlReaderDelegator xmlReader, out string name)
219 if (xmlReader.IsStartElement(JsonGlobals.itemDictionaryString, JsonGlobals.itemDictionaryString))
221 if (xmlReader.MoveToAttribute(JsonGlobals.itemString))
223 name = xmlReader.Value;
231 public static string GetJsonMemberName(XmlReaderDelegator xmlReader)
234 if (!TryGetJsonLocalName(xmlReader, out name))
236 name = xmlReader.LocalName;
241 public static void ThrowMissingRequiredMembers(object obj, XmlDictionaryString[] memberNames, byte[] expectedElements, byte[] requiredElements)
243 StringBuilder stringBuilder = new StringBuilder();
244 int missingMembersCount = 0;
245 for (int i = 0; i < memberNames.Length; i++)
247 if (IsBitSet(expectedElements, i) && IsBitSet(requiredElements, i))
249 if (stringBuilder.Length != 0)
250 stringBuilder.Append(", ");
251 stringBuilder.Append(memberNames[i]);
252 missingMembersCount++;
256 if (missingMembersCount == 1)
258 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
259 SR.JsonOneRequiredMemberNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
263 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
264 SR.JsonRequiredMembersNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
270 public static void ThrowDuplicateMemberException(object obj, XmlDictionaryString[] memberNames, int memberIndex)
272 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(
273 SR.GetString(SR.JsonDuplicateMemberInInput, DataContract.GetClrTypeFullName(obj.GetType()), memberNames[memberIndex])));
276 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'BitFlagsGenerator'.",
277 Safe = "This method is safe to call.")]
278 [SecuritySafeCritical]
279 static bool IsBitSet(byte[] bytes, int bitIndex)
281 return BitFlagsGenerator.IsBitSet(bytes, bitIndex);
284 protected override bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
286 return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.arrayString;
289 protected override bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)
291 return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.objectString;
294 protected override XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
296 return new JsonReaderDelegator(xmlReader, this.dateTimeFormat);
299 internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
301 DataContract dataContract = base.GetDataContract(typeHandle, type);
302 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
306 internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
308 DataContract dataContract = base.GetDataContractSkipValidation(typeId, typeHandle, type);
309 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
313 internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
315 DataContract dataContract = base.GetDataContract(id, typeHandle);
316 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
320 protected override DataContract ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
322 return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract);