예제 #1
0
        /// <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));
        }
예제 #2
0
        /// <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);
        }