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;
11 using System.ServiceModel;
16 public class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
18 class XmlObjectSerializerReadContextComplexJson : XmlObjectSerializerReadContextComplex
21 string extensionDataValueType;
22 DateTimeFormat dateTimeFormat;
23 bool useSimpleDictionaryFormat;
25 public XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
26 : base(serializer, serializer.MaxItemsInObjectGraph,
27 new StreamingContext(StreamingContextStates.All),
28 serializer.IgnoreExtensionDataObject)
30 this.rootTypeDataContract = rootTypeDataContract;
31 this.serializerKnownTypeList = serializer.knownTypeList;
32 this.dataContractSurrogate = serializer.DataContractSurrogate;
33 this.dateTimeFormat = serializer.DateTimeFormat;
34 this.useSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat;
37 internal IList<Type> SerializerKnownTypeList
41 return this.serializerKnownTypeList;
45 public bool UseSimpleDictionaryFormat
49 return this.useSimpleDictionaryFormat;
53 protected override void StartReadExtensionDataValue(XmlReaderDelegator xmlReader)
55 extensionDataValueType = xmlReader.GetAttribute(JsonGlobals.typeString);
58 protected override IDataNode ReadPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
62 switch (extensionDataValueType)
65 case JsonGlobals.stringString:
66 dataNode = new DataNode<string>(xmlReader.ReadContentAsString());
68 case JsonGlobals.booleanString:
69 dataNode = new DataNode<bool>(xmlReader.ReadContentAsBoolean());
71 case JsonGlobals.numberString:
72 dataNode = ReadNumericalPrimitiveExtensionDataValue(xmlReader);
75 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
76 XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonUnexpectedAttributeValue, extensionDataValueType)));
79 xmlReader.ReadEndElement();
83 IDataNode ReadNumericalPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader)
86 object numericalValue = JsonObjectDataContract.ParseJsonNumber(xmlReader.ReadContentAsString(), out type);
90 return new DataNode<byte>((byte)numericalValue);
92 return new DataNode<sbyte>((sbyte)numericalValue);
94 return new DataNode<short>((short)numericalValue);
96 return new DataNode<int>((int)numericalValue);
98 return new DataNode<long>((long)numericalValue);
100 return new DataNode<ushort>((ushort)numericalValue);
101 case TypeCode.UInt32:
102 return new DataNode<uint>((uint)numericalValue);
103 case TypeCode.UInt64:
104 return new DataNode<ulong>((ulong)numericalValue);
105 case TypeCode.Single:
106 return new DataNode<float>((float)numericalValue);
107 case TypeCode.Double:
108 return new DataNode<double>((double)numericalValue);
109 case TypeCode.Decimal:
110 return new DataNode<decimal>((decimal)numericalValue);
112 throw Fx.AssertAndThrow("JsonObjectDataContract.ParseJsonNumber shouldn't return a TypeCode that we're not expecting");
116 internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
118 return new XmlObjectSerializerReadContextComplexJson(serializer, rootTypeDataContract);
122 public override int GetArraySize()
124 internal override int GetArraySize()
130 protected override object ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
132 return DataContractJsonSerializer.ReadJsonValue(dataContract, reader, this);
136 public override void ReadAttributes(XmlReaderDelegator xmlReader)
138 internal override void ReadAttributes(XmlReaderDelegator xmlReader)
141 if (attributes == null)
142 attributes = new Attributes();
145 if (xmlReader.MoveToAttribute(JsonGlobals.typeString) && xmlReader.Value == JsonGlobals.nullString)
147 attributes.XsiNil = true;
149 else if (xmlReader.MoveToAttribute(JsonGlobals.serverTypeString))
151 XmlQualifiedName qualifiedTypeName = JsonReaderDelegator.ParseQualifiedName(xmlReader.Value);
152 attributes.XsiTypeName = qualifiedTypeName.Name;
154 string serverTypeNamespace = qualifiedTypeName.Namespace;
156 if (!string.IsNullOrEmpty(serverTypeNamespace))
158 switch (serverTypeNamespace[0])
161 serverTypeNamespace = string.Concat(Globals.DataContractXsdBaseNamespace, serverTypeNamespace.Substring(1));
164 if (serverTypeNamespace.Length >= 2)
166 switch (serverTypeNamespace[1])
170 serverTypeNamespace = serverTypeNamespace.Substring(1);
182 attributes.XsiTypeNamespace = serverTypeNamespace;
184 xmlReader.MoveToElement();
187 public int GetJsonMemberIndex(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, int memberIndex, ExtensionDataObject extensionData)
189 int length = memberNames.Length;
192 for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
194 if (xmlReader.IsStartElement(memberNames[index], XmlDictionaryString.Empty))
200 if (TryGetJsonLocalName(xmlReader, out name))
202 for (int i = 0, index = (memberIndex + 1) % length; i < length; i++, index = (index + 1) % length)
204 if (memberNames[index].Value == name)
211 HandleMemberNotFound(xmlReader, extensionData, memberIndex);
215 internal static bool TryGetJsonLocalName(XmlReaderDelegator xmlReader, out string name)
217 if (xmlReader.IsStartElement(JsonGlobals.itemDictionaryString, JsonGlobals.itemDictionaryString))
219 if (xmlReader.MoveToAttribute(JsonGlobals.itemString))
221 name = xmlReader.Value;
229 public static string GetJsonMemberName(XmlReaderDelegator xmlReader)
232 if (!TryGetJsonLocalName(xmlReader, out name))
234 name = xmlReader.LocalName;
239 public static void ThrowMissingRequiredMembers(object obj, XmlDictionaryString[] memberNames, byte[] expectedElements, byte[] requiredElements)
241 StringBuilder stringBuilder = new StringBuilder();
242 int missingMembersCount = 0;
243 for (int i = 0; i < memberNames.Length; i++)
245 if (IsBitSet(expectedElements, i) && IsBitSet(requiredElements, i))
247 if (stringBuilder.Length != 0)
248 stringBuilder.Append(", ");
249 stringBuilder.Append(memberNames[i]);
250 missingMembersCount++;
254 if (missingMembersCount == 1)
256 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
257 SR.JsonOneRequiredMemberNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
261 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(
262 SR.JsonRequiredMembersNotFound, DataContract.GetClrTypeFullName(obj.GetType()), stringBuilder.ToString())));
268 public static void ThrowDuplicateMemberException(object obj, XmlDictionaryString[] memberNames, int memberIndex)
270 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(
271 SR.GetString(SR.JsonDuplicateMemberInInput, DataContract.GetClrTypeFullName(obj.GetType()), memberNames[memberIndex])));
274 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'BitFlagsGenerator'.",
275 Safe = "This method is safe to call.")]
276 [SecuritySafeCritical]
277 static bool IsBitSet(byte[] bytes, int bitIndex)
279 return BitFlagsGenerator.IsBitSet(bytes, bitIndex);
282 protected override bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
284 return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.arrayString;
287 protected override bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)
289 return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.objectString;
292 protected override XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
294 return new JsonReaderDelegator(xmlReader, this.dateTimeFormat);
297 internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
299 DataContract dataContract = base.GetDataContract(typeHandle, type);
300 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
304 internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
306 DataContract dataContract = base.GetDataContractSkipValidation(typeId, typeHandle, type);
307 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
311 internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
313 DataContract dataContract = base.GetDataContract(id, typeHandle);
314 DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
318 protected override DataContract ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
320 return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract);