/// <summary> /// Deserializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> /// <returns>The <see cref="SerializationObject"/> representing the deserialized value or result.</returns> protected override SerializationObject DeserializeMember(ISerializationContext <JsonSerializationContextInfo> context, MemberValue memberValue) { var serializationContext = context.Context; var jsonProperties = serializationContext.JsonProperties; if (jsonProperties != null) { if (PreserveReferences) { var graphRefIdPropertyName = string.Format("${0}_{1}", memberValue.NameForSerialization, GraphRefId); if (jsonProperties.ContainsKey(graphRefIdPropertyName)) { var graphId = (int)jsonProperties[graphRefIdPropertyName].Value; var referenceManager = context.ReferenceManager; var referenceInfo = referenceManager.GetInfoById(graphId); if (referenceInfo == null) { Log.Error("Expected to find graph object with id '{0}' in ReferenceManager, but it was not found. Defaulting value for member '{1}' to null", graphId, memberValue.Name); return(null); } return(SerializationObject.SucceededToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name, referenceInfo.Instance)); } } if (memberValue.MemberGroup == SerializationMemberGroup.Dictionary) { var dictionary = CreateModelInstance(memberValue.MemberType) as IDictionary; var keyType = typeof(object); var valueType = typeof(object); if (memberValue.MemberType.IsGenericTypeEx()) { var genericArguments = memberValue.MemberType.GetGenericArgumentsEx(); if (genericArguments.Length == 2) { keyType = genericArguments[0]; valueType = genericArguments[1]; } } foreach (var jsonPropertyKeyValuePair in jsonProperties) { var jsonProperty = jsonPropertyKeyValuePair.Value; object deserializedItem = null; object key = jsonProperty.Name; if (keyType != typeof(object)) { key = StringToObjectHelper.ToRightType(keyType, jsonProperty.Name); } var typeToDeserialize = valueType; if (jsonProperty.Value != null) { if (jsonProperty.Value.Type != JTokenType.Object) { switch (jsonProperty.Value.Type) { case JTokenType.Integer: typeToDeserialize = typeof(int); break; case JTokenType.Float: typeToDeserialize = typeof(float); break; case JTokenType.String: typeToDeserialize = typeof(string); break; case JTokenType.Boolean: typeToDeserialize = typeof(bool); break; case JTokenType.Date: typeToDeserialize = typeof(DateTime); break; case JTokenType.Guid: typeToDeserialize = typeof(Guid); break; case JTokenType.Uri: typeToDeserialize = typeof(Uri); break; case JTokenType.TimeSpan: typeToDeserialize = typeof(TimeSpan); break; } } } var shouldValueTypeBeHandledByExternalSerializer = ShouldExternalSerializerHandleMember(typeToDeserialize); if (shouldValueTypeBeHandledByExternalSerializer) { deserializedItem = jsonProperty.Value.ToObject(valueType, serializationContext.JsonSerializer); } else { var reader = jsonProperty.Value.CreateReader(context.Configuration); reader.Culture = context.Configuration.Culture; deserializedItem = Deserialize(valueType, reader, context.Configuration); } dictionary[key] = deserializedItem; } return(SerializationObject.SucceededToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name, dictionary)); } if (jsonProperties.ContainsKey(memberValue.NameForSerialization)) { var jsonProperty = jsonProperties[memberValue.NameForSerialization]; var jsonValue = jsonProperty.Value; if (jsonValue != null) { object finalMemberValue = null; var valueType = memberValue.GetBestMemberType(); if (valueType.IsEnumEx()) { var enumName = Enum.GetName(valueType, (int)jsonValue); if (!string.IsNullOrWhiteSpace(enumName)) { finalMemberValue = Enum.Parse(valueType, enumName, false); } } else { try { var isDeserialized = false; if (jsonValue.Type == JTokenType.String && ShouldSerializeUsingParseAndToString(memberValue, false)) { var tempValue = memberValue.Value; memberValue.Value = (string)jsonValue; var parsedValue = DeserializeUsingObjectParse(context, memberValue); if (parsedValue != null) { finalMemberValue = parsedValue; isDeserialized = true; } else { memberValue.Value = tempValue; } } if (!isDeserialized) { if (ShouldExternalSerializerHandleMember(memberValue)) { finalMemberValue = jsonValue.ToObject(valueType, serializationContext.JsonSerializer); } else if (ShouldSerializeAsCollection(memberValue)) { finalMemberValue = Deserialize(valueType, jsonProperty.Value.CreateReader(context.Configuration), context.Configuration); } else { if (jsonValue.HasValues) { var finalValueType = valueType; var typeNameValue = jsonValue.Value <string>(TypeName); if (!string.IsNullOrWhiteSpace(typeNameValue)) { finalValueType = TypeCache.GetType(typeNameValue); } // Serialize ourselves finalMemberValue = Deserialize(finalValueType, jsonValue.CreateReader(context.Configuration), context.Configuration); } } } } catch (Exception ex) { Log.Debug(ex, "Failed to parse json value for '{0}', treating value as string", memberValue.Name); // As a fallback, interpret as a string (might be a modifier) finalMemberValue = (string)jsonValue; } } if (finalMemberValue != null) { if (PreserveReferences && finalMemberValue.GetType().IsClassType()) { var graphIdPropertyName = string.Format("${0}_{1}", memberValue.NameForSerialization, GraphId); if (jsonProperties.ContainsKey(graphIdPropertyName)) { var graphId = (int)jsonProperties[graphIdPropertyName].Value; var referenceManager = context.ReferenceManager; referenceManager.RegisterManually(graphId, finalMemberValue); } } return(SerializationObject.SucceededToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name, finalMemberValue)); } } } } var shouldSerializeAsCollection = ShouldSerializeAsCollection(memberValue); if (shouldSerializeAsCollection) { var collection = new List <object>(); var jArray = context.Context.JsonArray; if (jArray != null) { var memberType = memberValue.GetBestMemberType(); var collectionItemType = memberType.GetCollectionElementType(); var shouldBeHandledByExternalSerializer = ShouldExternalSerializerHandleMember(collectionItemType); foreach (var item in jArray.Children()) { object deserializedItem = null; if (shouldBeHandledByExternalSerializer) { deserializedItem = item.ToObject(collectionItemType, serializationContext.JsonSerializer); } else { deserializedItem = Deserialize(collectionItemType, item.CreateReader(context.Configuration), context.Configuration); } collection.Add(deserializedItem); } } return(SerializationObject.SucceededToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name, collection)); } return(SerializationObject.FailedToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name)); }
/// <summary> /// Writes the XML element to the xml element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="elementName">Name of the element.</param> /// <param name="memberValue">The member value.</param> /// <param name="modelType">Type of the model.</param> private void WriteXmlElement(ISerializationContext <XmlSerializationContextInfo> context, XElement element, string elementName, MemberValue memberValue, Type modelType) { var contextInfo = context.Context; var namespacePrefix = GetNamespacePrefix(); var stringBuilder = new StringBuilder(); var xmlWriterSettings = new XmlWriterSettings(); XmlNamespace xmlNamespace = null; xmlWriterSettings.OmitXmlDeclaration = true; xmlWriterSettings.CheckCharacters = false; xmlWriterSettings.ConformanceLevel = ConformanceLevel.Fragment; xmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates; #if XAMARIN var defaultNamespace = "http://www.w3.org/2000/xmlns/"; #endif using (var xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings)) { if (memberValue.Value == null) { xmlWriter.WriteStartElement(elementName); #if XAMARIN xmlWriter.WriteAttributeString("xmlns", namespacePrefix, defaultNamespace, "http://catel.codeplex.com"); #endif xmlWriter.WriteAttributeString(namespacePrefix, "IsNull", null, "true"); xmlWriter.WriteEndElement(); } else { var memberTypeToSerialize = memberValue.GetBestMemberType(); var serializer = _dataContractSerializerFactory.GetDataContractSerializer(modelType, memberTypeToSerialize, elementName, null, null); ReferenceInfo referenceInfo = null; var serializeElement = true; if (memberValue.MemberGroup != SerializationMemberGroup.Collection) { var isClassType = memberTypeToSerialize.IsClassType(); if (isClassType) { var referenceManager = context.ReferenceManager; referenceInfo = referenceManager.GetInfo(memberValue.Value); if (!referenceInfo.IsFirstUsage) { // Note: we don't want to call GetSafeFullName if we don't have to if (LogManager.IsDebugEnabled ?? false) { Log.Debug("Existing reference detected for element type '{0}' with id '{1}', only storing id", memberTypeToSerialize.GetSafeFullName(false), referenceInfo.Id); } //serializer.WriteStartObject(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlWriter.WriteAttributeString(namespacePrefix, GraphRefId, null, referenceInfo.Id.ToString()); //serializer.WriteEndObject(xmlWriter); xmlWriter.WriteEndElement(); serializeElement = false; } } } if (serializeElement) { //var xmlSerializer = new System.Xml.Serialization.XmlSerializer(memberTypeToSerialize, namespacePrefix); //xmlSerializer.Serialize(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlNamespace = _xmlNamespaceManager.GetNamespace(memberTypeToSerialize, namespacePrefix); if (xmlNamespace != null) { xmlWriter.WriteAttributeString("xmlns", xmlNamespace.Prefix, null, xmlNamespace.Uri); } if (referenceInfo != null) { xmlWriter.WriteAttributeString(namespacePrefix, GraphId, null, referenceInfo.Id.ToString()); } if (memberTypeToSerialize != memberValue.MemberType) { var memberTypeToSerializerName = TypeHelper.GetTypeName(memberTypeToSerialize.FullName); xmlWriter.WriteAttributeString(namespacePrefix, "type", null, memberTypeToSerializerName); } // In special cases, we need to write our own collection items. One case is where a custom ModelBase // implements IList and gets inside a StackOverflow var serialized = false; if (ShouldSerializeModelAsCollection(memberValue.GetBestMemberType())) { var collection = memberValue.Value as IEnumerable; if (collection != null) { foreach (var item in collection) { var subItemElementName = GetXmlElementName(item.GetType(), item, null); xmlWriter.WriteStartElement(subItemElementName); serializer.WriteObjectContent(xmlWriter, item); xmlWriter.WriteEndElement(); } serialized = true; } } if (!serialized) { serializer.WriteObjectContent(xmlWriter, memberValue.Value); } xmlWriter.WriteEndElement(); } } } EnsureNamespaceInXmlDocument(element, xmlNamespace); var childContent = stringBuilder.ToString(); var childElement = XElement.Parse(childContent); element.Add(childElement); }