private void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, string qualifiedTypeName)
        {
            TypeNameHandling resolvedTypeNameHandling =
                ((member != null) ? member.TypeNameHandling : null)
                ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
                ?? ((containerMember != null) ? containerMember.ItemTypeNameHandling : null)
                ?? Serializer._typeNameHandling;

            if (resolvedTypeNameHandling != TypeNameHandling.None)
            {
                string typeName;
                string assemblyName;
                ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName, out typeName, out assemblyName);

                Type specifiedType;
                try
                {
                    specifiedType = Serializer._binder.BindToType(assemblyName, typeName);
                }
                catch (Exception ex)
                {
                    throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex);
                }

                if (specifiedType == null)
                {
                    throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName));
                }

                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                {
                    TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName, specifiedType)), null);
                }

                if (objectType != null
            #if !(NET35 || NET20 || PORTABLE40)
                    && objectType != typeof(IDynamicMetaObjectProvider)
            #endif
                    && !objectType.IsAssignableFrom(specifiedType))
                {
                    throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName));
                }

                objectType = specifiedType;
                contract = GetContractSafe(specifiedType);
            }
        }
 internal string GetExpectedDescription(JsonContract contract)
 {
     switch (contract.ContractType)
     {
         case JsonContractType.Object:
         case JsonContractType.Dictionary:
     #if !(DOTNET || PORTABLE || PORTABLE40)
         case JsonContractType.Serializable:
     #endif
     #if !(NET35 || NET20 || PORTABLE40)
         case JsonContractType.Dynamic:
     #endif
             return @"JSON object (e.g. {""name"":""value""})";
         case JsonContractType.Array:
             return @"JSON array (e.g. [1,2,3])";
         case JsonContractType.Primitive:
             return @"JSON primitive value (e.g. string, number, boolean, null)";
         case JsonContractType.String:
             return @"JSON string value";
         default:
             throw new ArgumentOutOfRangeException();
     }
 }
        private void OnDeserializing(JsonReader reader, JsonContract contract, object value)
        {
            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
            {
                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
            }

            contract.InvokeOnDeserializing(value, Serializer._context);
        }
        private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
        {
            id = null;
            newValue = null;

            if (reader.TokenType == JsonToken.PropertyName)
            {
                string propertyName = reader.Value.ToString();

                if (propertyName.Length > 0 && propertyName[0] == '$')
                {
                    // read metadata properties
                    // $type, $id, $ref, etc
                    bool metadataProperty;

                    do
                    {
                        propertyName = reader.Value.ToString();

                        if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal))
                        {
                            reader.ReadAndAssert();
                            if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null)
                            {
                                throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));
                            }

                            string reference = (reader.Value != null) ? reader.Value.ToString() : null;

                            reader.ReadAndAssert();

                            if (reference != null)
                            {
                                if (reader.TokenType == JsonToken.PropertyName)
                                {
                                    throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));
                                }

                                newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference);

                                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                                {
                                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null);
                                }

                                return true;
                            }
                            else
                            {
                                metadataProperty = true;
                            }
                        }
                        else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal))
                        {
                            reader.ReadAndAssert();
                            string qualifiedTypeName = reader.Value.ToString();

                            ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName);

                            reader.ReadAndAssert();

                            metadataProperty = true;
                        }
                        else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal))
                        {
                            reader.ReadAndAssert();

                            id = (reader.Value != null) ? reader.Value.ToString() : null;

                            reader.ReadAndAssert();
                            metadataProperty = true;
                        }
                        else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal))
                        {
                            reader.ReadAndAssert();
                            object list = CreateList(reader, objectType, contract, member, existingValue, id);
                            reader.ReadAndAssert();
                            newValue = list;
                            return true;
                        }
                        else
                        {
                            metadataProperty = false;
                        }
                    } while (metadataProperty && reader.TokenType == JsonToken.PropertyName);
                }
            }
            return false;
        }
        private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
        {
            if (contract == null)
            {
                throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType));
            }

            JsonArrayContract arrayContract = contract as JsonArrayContract;
            if (arrayContract == null)
            {
                string message = @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine +
                                 @"To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array." + Environment.NewLine;
                message = message.FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract));

                throw JsonSerializationException.Create(reader, message);
            }

            return arrayContract;
        }
 private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty)
 {
     JsonConverter converter = null;
     if (memberConverter != null)
     {
         // member attribute converter
         converter = memberConverter;
     }
     else if (containerProperty != null && containerProperty.ItemConverter != null)
     {
         converter = containerProperty.ItemConverter;
     }
     else if (containerContract != null && containerContract.ItemConverter != null)
     {
         converter = containerContract.ItemConverter;
     }
     else if (contract != null)
     {
         JsonConverter matchingConverter;
         if (contract.Converter != null)
         {
             // class attribute converter
             converter = contract.Converter;
         }
         else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null)
         {
             // passed in converters
             converter = matchingConverter;
         }
         else if (contract.InternalConverter != null)
         {
             // internally specified converter
             converter = contract.InternalConverter;
         }
     }
     return converter;
 }
        private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            writer.WriteStartObject();

            bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects);
            // don't make readonly fields the referenced value because they can't be deserialized to
            if (isReference && (member == null || member.Writable))
            {
                WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
            }
            if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
            {
                WriteTypeProperty(writer, contract.UnderlyingType);
            }
        }
        private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }

            JsonConverter converter =
                ((member != null) ? member.Converter : null) ??
                ((containerProperty != null) ? containerProperty.ItemConverter : null) ??
                ((containerContract != null) ? containerContract.ItemConverter : null) ??
                valueContract.Converter ??
                Serializer.GetMatchingConverter(valueContract.UnderlyingType) ??
                valueContract.InternalConverter;

            if (converter != null && converter.CanWrite)
            {
                SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty);
                return;
            }

            switch (valueContract.ContractType)
            {
                case JsonContractType.Object:
                    SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
                    break;
                case JsonContractType.Array:
                    JsonArrayContract arrayContract = (JsonArrayContract)valueContract;
                    if (!arrayContract.IsMultidimensionalArray)
                    {
                        SerializeList(writer, (IEnumerable)value, arrayContract, member, containerContract, containerProperty);
                    }
                    else
                    {
                        SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty);
                    }
                    break;
                case JsonContractType.Primitive:
                    SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
                    break;
                case JsonContractType.String:
                    SerializeString(writer, value, (JsonStringContract)valueContract);
                    break;
                case JsonContractType.Dictionary:
                    JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)valueContract;
                    SerializeDictionary(writer, (value is IDictionary) ? (IDictionary)value : dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
                    break;
#if !(NET35 || NET20 || PORTABLE40)
                case JsonContractType.Dynamic:
                    SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
                    break;
#endif
#if !(DOTNET || PORTABLE40 || PORTABLE)
                case JsonContractType.Serializable:
                    SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
                    break;
#endif
                case JsonContractType.Linq:
                    ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray());
                    break;
            }
        }
        private void OnSerialized(JsonWriter writer, JsonContract contract, object value)
        {
            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
            {
                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
            }

            contract.InvokeOnSerialized(value, Serializer._context);
        }
        private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue)
        {
            if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value))
            {
                if (property.PropertyContract == null)
                {
                    property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);
                }

                memberValue = property.ValueProvider.GetValue(value);
                memberContract = (property.PropertyContract.IsSealed) ? property.PropertyContract : GetContractSafe(memberValue);

                if (ShouldWriteProperty(memberValue, property))
                {
                    if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
                    {
                        property.WritePropertyName(writer);
                        WriteReference(writer, memberValue);
                        return false;
                    }

                    if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
                    {
                        return false;
                    }

                    if (memberValue == null)
                    {
                        JsonObjectContract objectContract = contract as JsonObjectContract;
                        Required resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default;
                        if (resolvedRequired == Required.Always)
                        {
                            throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
                        }
                        if (resolvedRequired == Required.DisallowNull)
                        {
                            throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
                        }
                    }

                    return true;
                }
            }

            memberContract = null;
            memberValue = null;
            return false;
        }
        private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
            {
                return true;
            }

            ReferenceLoopHandling? referenceLoopHandling = null;

            if (property != null)
            {
                referenceLoopHandling = property.ReferenceLoopHandling;
            }

            if (referenceLoopHandling == null && containerProperty != null)
            {
                referenceLoopHandling = containerProperty.ItemReferenceLoopHandling;
            }

            if (referenceLoopHandling == null && containerContract != null)
            {
                referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
            }

            bool exists = (Serializer._equalityComparer != null)
                ? _serializeStack.Contains(value, Serializer._equalityComparer)
                : _serializeStack.Contains(value);

            if (exists)
            {
                string message = "Self referencing loop detected";
                if (property != null)
                {
                    message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
                }
                message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());

                switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling))
                {
                    case ReferenceLoopHandling.Error:
                        throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);
                    case ReferenceLoopHandling.Ignore:
                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                        {
                            TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null);
                        }

                        return false;
                    case ReferenceLoopHandling.Serialize:
                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                        {
                            TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null);
                        }

                        return true;
                }
            }

            return true;
        }
        private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            if (value == null)
            {
                return false;
            }
            if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
            {
                return false;
            }

            bool? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty);

            if (isReference == null)
            {
                if (valueContract.ContractType == JsonContractType.Array)
                {
                    isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
                }
                else
                {
                    isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects);
                }
            }

            if (!isReference.GetValueOrDefault())
            {
                return false;
            }

            return Serializer.GetReferenceResolver().IsReferenced(this, value);
        }
        private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            bool? isReference = null;

            // value could be coming from a dictionary or array and not have a property
            if (property != null)
            {
                isReference = property.IsReference;
            }

            if (isReference == null && containerProperty != null)
            {
                isReference = containerProperty.ItemIsReference;
            }

            if (isReference == null && collectionContract != null)
            {
                isReference = collectionContract.ItemIsReference;
            }

            if (isReference == null)
            {
                isReference = contract.IsReference;
            }

            return isReference;
        }
        private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue)
        {
            currentValue = null;
            useExistingValue = false;
            propertyContract = null;
            gottenCurrentValue = false;

            if (property.Ignored)
            {
                return true;
            }

            JsonToken tokenType = reader.TokenType;

            if (property.PropertyContract == null)
            {
                property.PropertyContract = GetContractSafe(property.PropertyType);
            }

            ObjectCreationHandling objectCreationHandling =
                property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling);

            if ((objectCreationHandling != ObjectCreationHandling.Replace)
                && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject)
                && property.Readable)
            {
                currentValue = property.ValueProvider.GetValue(target);
                gottenCurrentValue = true;

                if (currentValue != null)
                {
                    propertyContract = GetContractSafe(currentValue.GetType());

                    useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
                }
            }

            if (!property.Writable && !useExistingValue)
            {
                return true;
            }

            // test tokentype here because null might not be convertable to some types, e.g. ignoring null when applied to DateTime
            if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && tokenType == JsonToken.Null)
            {
                return true;
            }

            // test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime
            if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
                && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate)
                && JsonTokenUtils.IsPrimitiveToken(tokenType)
                && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue()))
            {
                return true;
            }

            if (currentValue == null)
            {
                propertyContract = property.PropertyContract;
            }
            else
            {
                propertyContract = GetContractSafe(currentValue.GetType());

                if (propertyContract != property.PropertyContract)
                {
                    propertyConverter = GetConverter(propertyContract, property.MemberConverter, containerContract, containerProperty);
                }
            }

            return false;
        }
        private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
            {
                WriteReference(writer, value);
            }
            else
            {
                if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty))
                {
                    return;
                }

                _serializeStack.Add(value);

                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                {
                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
                }

                converter.WriteJson(writer, value, GetInternalSerializer());

                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                {
                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
                }

                _serializeStack.RemoveAt(_serializeStack.Count - 1);
            }
        }
        private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id)
        {
            object value;

            if (HasNoDefinedType(contract))
            {
                return CreateJToken(reader, contract);
            }

            JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract);

            if (existingValue == null)
            {
                bool createdFromNonDefaultCreator;
                IList list = CreateNewList(reader, arrayContract, out createdFromNonDefaultCreator);

                if (createdFromNonDefaultCreator)
                {
                    if (id != null)
                    {
                        throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                    }

                    if (contract.OnSerializingCallbacks.Count > 0)
                    {
                        throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                    }

                    if (contract.OnErrorCallbacks.Count > 0)
                    {
                        throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                    }

                    if (!arrayContract.HasParameterizedCreatorInternal && !arrayContract.IsArray)
                    {
                        throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                    }
                }

                if (!arrayContract.IsMultidimensionalArray)
                {
                    PopulateList(list, reader, arrayContract, member, id);
                }
                else
                {
                    PopulateMultidimensionalArray(list, reader, arrayContract, member, id);
                }

                if (createdFromNonDefaultCreator)
                {
                    if (arrayContract.IsMultidimensionalArray)
                    {
                        list = CollectionUtils.ToMultidimensionalArray(list, arrayContract.CollectionItemType, contract.CreatedType.GetArrayRank());
                    }
                    else if (arrayContract.IsArray)
                    {
                        Array a = Array.CreateInstance(arrayContract.CollectionItemType, list.Count);
                        list.CopyTo(a, 0);
                        list = a;
                    }
                    else
                    {
                        ObjectConstructor<object> creator = arrayContract.OverrideCreator ?? arrayContract.ParameterizedCreator;

                        return creator(list);
                    }
                }
                else if (list is IWrappedCollection)
                {
                    return ((IWrappedCollection)list).UnderlyingCollection;
                }

                value = list;
            }
            else
            {
                if (!arrayContract.CanDeserialize)
                {
                    throw JsonSerializationException.Create(reader, "Cannot populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType));
                }

                value = PopulateList((arrayContract.ShouldCreateWrapper) ? arrayContract.CreateWrapper(existingValue) : (IList)existingValue, reader, arrayContract, member, id);
            }

            return value;
        }
        private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            TypeNameHandling resolvedTypeNameHandling =
                ((member != null) ? member.TypeNameHandling : null)
                ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
                ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
                ?? Serializer._typeNameHandling;

            if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag))
            {
                return true;
            }

            // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default)
            if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto))
            {
                if (member != null)
                {
                    if (contract.UnderlyingType != member.PropertyContract.CreatedType)
                    {
                        return true;
                    }
                }
                else if (containerContract != null)
                {
                    if (containerContract.ItemContract == null || contract.UnderlyingType != containerContract.ItemContract.CreatedType)
                    {
                        return true;
                    }
                }
                else if (_rootType != null && _serializeStack.Count == _rootLevel)
                {
                    JsonContract rootContract = Serializer._contractResolver.ResolveContract(_rootType);

                    if (contract.UnderlyingType != rootContract.CreatedType)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
        {
            if (contract != null && contract.ContractType == JsonContractType.Linq)
            {
                return CreateJToken(reader, contract);
            }

            do
            {
                switch (reader.TokenType)
                {
                    // populate a typed object or generic dictionary/array
                    // depending upon whether an objectType was supplied
                    case JsonToken.StartObject:
                        return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue);
                    case JsonToken.StartArray:
                        return CreateList(reader, objectType, contract, member, existingValue, null);
                    case JsonToken.Integer:
                    case JsonToken.Float:
                    case JsonToken.Boolean:
                    case JsonToken.Date:
                    case JsonToken.Bytes:
                        return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
                    case JsonToken.String:
                        string s = (string)reader.Value;

                        // convert empty string to null automatically for nullable types
                        if (CoerceEmptyStringToNull(objectType, contract, s))
                        {
                            return null;
                        }

                        // string that needs to be returned as a byte array should be base 64 decoded
                        if (objectType == typeof(byte[]))
                        {
                            return Convert.FromBase64String(s);
                        }

                        return EnsureType(reader, s, CultureInfo.InvariantCulture, contract, objectType);
                    case JsonToken.StartConstructor:
                        string constructorName = reader.Value.ToString();

                        return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType);
                    case JsonToken.Null:
                    case JsonToken.Undefined:
            #if !(DOTNET || PORTABLE40 || PORTABLE)
                        if (objectType == typeof(DBNull))
                        {
                            return DBNull.Value;
                        }
            #endif

                        return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
                    case JsonToken.Raw:
                        return new JRaw((string)reader.Value);
                    case JsonToken.Comment:
                        // ignore
                        break;
                    default:
                        throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType);
                }
            } while (reader.Read());

            throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
        }
Beispiel #19
0
        private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            IWrappedDictionary wrappedDictionary    = values as IWrappedDictionary;
            object             underlyingDictionary = wrappedDictionary != null ? wrappedDictionary.UnderlyingDictionary : values;

            OnSerializing(writer, contract, underlyingDictionary);
            _serializeStack.Add(underlyingDictionary);

            WriteObjectStart(writer, underlyingDictionary, contract, member, collectionContract, containerProperty);

            if (contract.ItemContract == null)
            {
                contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
            }

            if (contract.KeyContract == null)
            {
                contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object));
            }

            int initialDepth = writer.Top;

            foreach (DictionaryEntry entry in values)
            {
                bool   escape;
                string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);

                propertyName = (contract.DictionaryKeyResolver != null)
                    ? contract.DictionaryKeyResolver(propertyName)
                    : propertyName;

                try
                {
                    object       value         = entry.Value;
                    JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

                    if (ShouldWriteReference(value, null, valueContract, contract, member))
                    {
                        writer.WritePropertyName(propertyName, escape);
                        WriteReference(writer, value);
                    }
                    else
                    {
                        if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
                        {
                            continue;
                        }

                        writer.WritePropertyName(propertyName, escape);

                        SerializeValue(writer, value, valueContract, null, contract, member);
                    }
                }
                catch (Exception ex)
                {
                    if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
                    {
                        HandleError(writer, initialDepth);
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, underlyingDictionary);
        }
        private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType)
        {
            if (targetType == null)
            {
                return value;
            }

            Type valueType = ReflectionUtils.GetObjectType(value);

            // type of value and type of target don't match
            // attempt to convert value's type to target's type
            if (valueType != targetType)
            {
                if (value == null && contract.IsNullable)
                {
                    return null;
                }

                try
                {
                    if (contract.IsConvertable)
                    {
                        JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;

                        if (contract.IsEnum)
                        {
                            if (value is string)
                            {
                                return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true);
                            }
                            if (ConvertUtils.IsInteger(primitiveContract.TypeCode))
                            {
                                return Enum.ToObject(contract.NonNullableUnderlyingType, value);
                            }
                        }

            #if !(PORTABLE || PORTABLE40 || NET35 || NET20)
                        if (value is BigInteger)
                        {
                            return ConvertUtils.FromBigInteger((BigInteger)value, contract.NonNullableUnderlyingType);
                        }
            #endif

                        // this won't work when converting to a custom IConvertible
                        return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
                    }

                    return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType);
                }
                catch (Exception ex)
                {
                    throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(value), targetType), ex);
                }
            }

            return value;
        }
Beispiel #21
0
        private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }

            JsonConverter converter =
                ((member != null) ? member.Converter : null) ??
                ((containerProperty != null) ? containerProperty.ItemConverter : null) ??
                ((containerContract != null) ? containerContract.ItemConverter : null) ??
                valueContract.Converter ??
                Serializer.GetMatchingConverter(valueContract.UnderlyingType) ??
                valueContract.InternalConverter;

            if (converter != null && converter.CanWrite)
            {
                SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty);
                return;
            }

            switch (valueContract.ContractType)
            {
            case JsonContractType.Object:
                SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
                break;

            case JsonContractType.Array:
                JsonArrayContract arrayContract = (JsonArrayContract)valueContract;
                if (!arrayContract.IsMultidimensionalArray)
                {
                    SerializeList(writer, (IEnumerable)value, arrayContract, member, containerContract, containerProperty);
                }
                else
                {
                    SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty);
                }
                break;

            case JsonContractType.Primitive:
                SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
                break;

            case JsonContractType.String:
                SerializeString(writer, value, (JsonStringContract)valueContract);
                break;

            case JsonContractType.Dictionary:
                JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)valueContract;
                SerializeDictionary(writer, (value is IDictionary) ? (IDictionary)value : dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
                break;

#if !(NET35 || NET20 || PORTABLE40)
            case JsonContractType.Dynamic:
                SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
                break;
#endif
#if !(DOTNET || PORTABLE40 || PORTABLE)
            case JsonContractType.Serializable:
                SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
                break;
#endif
            case JsonContractType.Linq:
                ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray());
                break;
            }
        }
 private bool HasNoDefinedType(JsonContract contract)
 {
     return (contract == null || contract.UnderlyingType == typeof(object) || contract.ContractType == JsonContractType.Linq
     #if !(NET35 || NET20 || PORTABLE40)
             || contract.UnderlyingType == typeof(IDynamicMetaObjectProvider)
     #endif
         );
 }
Beispiel #23
0
        private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
            {
                return(true);
            }

            ReferenceLoopHandling?referenceLoopHandling = null;

            if (property != null)
            {
                referenceLoopHandling = property.ReferenceLoopHandling;
            }

            if (referenceLoopHandling == null && containerProperty != null)
            {
                referenceLoopHandling = containerProperty.ItemReferenceLoopHandling;
            }

            if (referenceLoopHandling == null && containerContract != null)
            {
                referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
            }

            bool exists = (Serializer._equalityComparer != null)
                ? _serializeStack.Contains(value, Serializer._equalityComparer)
                : _serializeStack.Contains(value);

            if (exists)
            {
                string message = "Self referencing loop detected";
                if (property != null)
                {
                    message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
                }
                message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());

                switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling))
                {
                case ReferenceLoopHandling.Error:
                    throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);

                case ReferenceLoopHandling.Ignore:
                    if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                    {
                        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null);
                    }

                    return(false);

                case ReferenceLoopHandling.Serialize:
                    if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                    {
                        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null);
                    }

                    return(true);
                }
            }

            return(true);
        }
        private bool ReadForType(JsonReader reader, JsonContract contract, bool hasConverter)
        {
            // don't read properties with converters as a specific value
            // the value might be a string which will then get converted which will error if read as date for example
            if (hasConverter)
            {
                return reader.Read();
            }

            ReadType t = (contract != null) ? contract.InternalReadType : ReadType.Read;

            switch (t)
            {
                case ReadType.Read:
                    return reader.ReadAndMoveToContent();
                case ReadType.ReadAsInt32:
                    reader.ReadAsInt32();
                    break;
                case ReadType.ReadAsDecimal:
                    reader.ReadAsDecimal();
                    break;
                case ReadType.ReadAsDouble:
                    reader.ReadAsDouble();
                    break;
                case ReadType.ReadAsBytes:
                    reader.ReadAsBytes();
                    break;
                case ReadType.ReadAsBoolean:
                    reader.ReadAsBoolean();
                    break;
                case ReadType.ReadAsString:
                    reader.ReadAsString();
                    break;
                case ReadType.ReadAsDateTime:
                    reader.ReadAsDateTime();
                    break;
            #if !NET20
                case ReadType.ReadAsDateTimeOffset:
                    reader.ReadAsDateTimeOffset();
                    break;
            #endif
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return (reader.TokenType != JsonToken.None);
        }
Beispiel #25
0
        private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, value);

            _serializeStack.Add(value);

            WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

            int initialDepth = writer.Top;

            for (int index = 0; index < contract.Properties.Count; index++)
            {
                JsonProperty property = contract.Properties[index];
                try
                {
                    object       memberValue;
                    JsonContract memberContract;

                    if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
                    {
                        continue;
                    }

                    property.WritePropertyName(writer);
                    SerializeValue(writer, memberValue, memberContract, property, contract, member);
                }
                catch (Exception ex)
                {
                    if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
                    {
                        HandleError(writer, initialDepth);
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            if (contract.ExtensionDataGetter != null)
            {
                IEnumerable <KeyValuePair <object, object> > extensionData = contract.ExtensionDataGetter(value);
                if (extensionData != null)
                {
                    foreach (KeyValuePair <object, object> e in extensionData)
                    {
                        JsonContract keyContract   = GetContractSafe(e.Key);
                        JsonContract valueContract = GetContractSafe(e.Value);

                        bool   escape;
                        string propertyName = GetPropertyName(writer, e.Key, keyContract, out escape);

                        if (ShouldWriteReference(e.Value, null, valueContract, contract, member))
                        {
                            writer.WritePropertyName(propertyName);
                            WriteReference(writer, e.Value);
                        }
                        else
                        {
                            if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member))
                            {
                                continue;
                            }

                            writer.WritePropertyName(propertyName);

                            SerializeValue(writer, e.Value, valueContract, null, contract, member);
                        }
                    }
                }
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, value);
        }
        private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
        {
            id = null;
            newValue = null;

            if (reader.TokenType == JsonToken.StartObject)
            {
                JObject current = (JObject)reader.CurrentToken;

                JToken refToken = current[JsonTypeReflector.RefPropertyName];
                if (refToken != null)
                {
                    if (refToken.Type != JTokenType.String && refToken.Type != JTokenType.Null)
                    {
                        throw JsonSerializationException.Create(refToken, refToken.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
                    }

                    JToken property = refToken.Parent;
                    JToken additionalContent = null;
                    if (property.Next != null)
                    {
                        additionalContent = property.Next;
                    }
                    else if (property.Previous != null)
                    {
                        additionalContent = property.Previous;
                    }

                    string reference = (string)refToken;

                    if (reference != null)
                    {
                        if (additionalContent != null)
                        {
                            throw JsonSerializationException.Create(additionalContent, additionalContent.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
                        }

                        newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference);

                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                        {
                            TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null);
                        }

                        reader.Skip();
                        return true;
                    }
                }
                JToken typeToken = current[JsonTypeReflector.TypePropertyName];
                if (typeToken != null)
                {
                    string qualifiedTypeName = (string)typeToken;
                    JsonReader typeTokenReader = typeToken.CreateReader();
                    typeTokenReader.ReadAndAssert();
                    ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName);

                    JToken valueToken = current[JsonTypeReflector.ValuePropertyName];
                    if (valueToken != null)
                    {
                        while (true)
                        {
                            reader.ReadAndAssert();
                            if (reader.TokenType == JsonToken.PropertyName)
                            {
                                if ((string)reader.Value == JsonTypeReflector.ValuePropertyName)
                                {
                                    return false;
                                }
                            }

                            reader.ReadAndAssert();
                            reader.Skip();
                        }
                    }
                }
                JToken idToken = current[JsonTypeReflector.IdPropertyName];
                if (idToken != null)
                {
                    id = (string)idToken;
                }
                JToken valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName];
                if (valuesToken != null)
                {
                    JsonReader listReader = valuesToken.CreateReader();
                    listReader.ReadAndAssert();
                    newValue = CreateList(listReader, objectType, contract, member, existingValue, id);

                    reader.Skip();
                    return true;
                }
            }

            reader.ReadAndAssert();
            return false;
        }
Beispiel #27
0
        private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue)
        {
            if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value))
            {
                if (property.PropertyContract == null)
                {
                    property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);
                }

                memberValue    = property.ValueProvider.GetValue(value);
                memberContract = (property.PropertyContract.IsSealed) ? property.PropertyContract : GetContractSafe(memberValue);

                if (ShouldWriteProperty(memberValue, property))
                {
                    if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
                    {
                        property.WritePropertyName(writer);
                        WriteReference(writer, memberValue);
                        return(false);
                    }

                    if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
                    {
                        return(false);
                    }

                    if (memberValue == null)
                    {
                        JsonObjectContract objectContract   = contract as JsonObjectContract;
                        Required           resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default;
                        if (resolvedRequired == Required.Always)
                        {
                            throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
                        }
                        if (resolvedRequired == Required.DisallowNull)
                        {
                            throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
                        }
                    }

                    return(true);
                }
            }

            memberContract = null;
            memberValue    = null;
            return(false);
        }
 private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object currentObject, string message)
 {
     try
     {
         throw JsonSerializationException.Create(reader, message);
     }
     catch (Exception ex)
     {
         if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex))
         {
             HandleError(reader, false, 0);
         }
         else
         {
             throw;
         }
     }
 }
Beispiel #29
0
        private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
            {
                WriteReference(writer, value);
            }
            else
            {
                if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty))
                {
                    return;
                }

                _serializeStack.Add(value);

                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                {
                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
                }

                converter.WriteJson(writer, value, GetInternalSerializer());

                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                {
                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
                }

                _serializeStack.RemoveAt(_serializeStack.Count - 1);
            }
        }
 private static bool CoerceEmptyStringToNull(Type objectType, JsonContract contract, string s)
 {
     return string.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable;
 }
Beispiel #31
0
        private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            IWrappedCollection wrappedCollection = values as IWrappedCollection;
            object             underlyingList    = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : values;

            OnSerializing(writer, contract, underlyingList);

            _serializeStack.Add(underlyingList);

            bool hasWrittenMetadataObject = WriteStartArray(writer, underlyingList, contract, member, collectionContract, containerProperty);

            writer.WriteStartArray();

            int initialDepth = writer.Top;

            int index = 0;

            // note that an error in the IEnumerable won't be caught
            foreach (object value in values)
            {
                try
                {
                    JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

                    if (ShouldWriteReference(value, null, valueContract, contract, member))
                    {
                        WriteReference(writer, value);
                    }
                    else
                    {
                        if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
                        {
                            SerializeValue(writer, value, valueContract, null, contract, member);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (IsErrorHandled(underlyingList, contract, index, null, writer.ContainerPath, ex))
                    {
                        HandleError(writer, initialDepth);
                    }
                    else
                    {
                        throw;
                    }
                }
                finally
                {
                    index++;
                }
            }

            writer.WriteEndArray();

            if (hasWrittenMetadataObject)
            {
                writer.WriteEndObject();
            }

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, underlyingList);
        }
        private JToken CreateJToken(JsonReader reader, JsonContract contract)
        {
            ValidationUtils.ArgumentNotNull(reader, nameof(reader));

            if (contract != null)
            {
                if (contract.UnderlyingType == typeof(JRaw))
                {
                    return JRaw.Create(reader);
                }
                if (reader.TokenType == JsonToken.Null
                    && !(contract.UnderlyingType == typeof(JValue) || contract.UnderlyingType == typeof(JToken)))
                {
                    return null;
                }
            }

            JToken token;
            using (JTokenWriter writer = new JTokenWriter())
            {
                writer.WriteToken(reader);
                token = writer.Token;
            }

            return token;
        }
Beispiel #33
0
        private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, value);
            _serializeStack.Add(value);

            WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

            int initialDepth = writer.Top;

            for (int index = 0; index < contract.Properties.Count; index++)
            {
                JsonProperty property = contract.Properties[index];

                // only write non-dynamic properties that have an explicit attribute
                if (property.HasMemberAttribute)
                {
                    try
                    {
                        object       memberValue;
                        JsonContract memberContract;

                        if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
                        {
                            continue;
                        }

                        property.WritePropertyName(writer);
                        SerializeValue(writer, memberValue, memberContract, property, contract, member);
                    }
                    catch (Exception ex)
                    {
                        if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
                        {
                            HandleError(writer, initialDepth);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }

            foreach (string memberName in value.GetDynamicMemberNames())
            {
                object memberValue;
                if (contract.TryGetMember(value, memberName, out memberValue))
                {
                    try
                    {
                        JsonContract valueContract = GetContractSafe(memberValue);

                        if (!ShouldWriteDynamicProperty(memberValue))
                        {
                            continue;
                        }

                        if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member))
                        {
                            string resolvedPropertyName = (contract.PropertyNameResolver != null)
                                ? contract.PropertyNameResolver(memberName)
                                : memberName;

                            writer.WritePropertyName(resolvedPropertyName);
                            SerializeValue(writer, memberValue, valueContract, null, contract, member);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (IsErrorHandled(value, contract, memberName, null, writer.ContainerPath, ex))
                        {
                            HandleError(writer, initialDepth);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);
            OnSerialized(writer, contract, value);
        }
        private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
        {
            string id;
            Type resolvedObjectType = objectType;

            if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore)
            {
                // don't look for metadata properties
                reader.ReadAndAssert();
                id = null;
            }
            else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead)
            {
                JTokenReader tokenReader = reader as JTokenReader;
                if (tokenReader == null)
                {
                    JToken t = JToken.ReadFrom(reader);
                    tokenReader = (JTokenReader)t.CreateReader();
                    tokenReader.Culture = reader.Culture;
                    tokenReader.DateFormatString = reader.DateFormatString;
                    tokenReader.DateParseHandling = reader.DateParseHandling;
                    tokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
                    tokenReader.FloatParseHandling = reader.FloatParseHandling;
                    tokenReader.SupportMultipleContent = reader.SupportMultipleContent;

                    // start
                    tokenReader.ReadAndAssert();

                    reader = tokenReader;
                }

                object newValue;
                if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
                {
                    return newValue;
                }
            }
            else
            {
                reader.ReadAndAssert();
                object newValue;
                if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
                {
                    return newValue;
                }
            }

            if (HasNoDefinedType(contract))
            {
                return CreateJObject(reader);
            }

            switch (contract.ContractType)
            {
                case JsonContractType.Object:
                {
                    bool createdFromNonDefaultCreator = false;
                    JsonObjectContract objectContract = (JsonObjectContract)contract;
                    object targetObject;
                    // check that if type name handling is being used that the existing value is compatible with the specified type
                    if (existingValue != null && (resolvedObjectType == objectType || resolvedObjectType.IsAssignableFrom(existingValue.GetType())))
                    {
                        targetObject = existingValue;
                    }
                    else
                    {
                        targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultCreator);
                    }

                    // don't populate if read from non-default creator because the object has already been read
                    if (createdFromNonDefaultCreator)
                    {
                        return targetObject;
                    }

                    return PopulateObject(targetObject, reader, objectContract, member, id);
                }
                case JsonContractType.Primitive:
                {
                    JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
                    // if the content is inside $value then read past it
                    if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore
                        && reader.TokenType == JsonToken.PropertyName
                        && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
                    {
                        reader.ReadAndAssert();

                        // the token should not be an object because the $type value could have been included in the object
                        // without needing the $value property
                        if (reader.TokenType == JsonToken.StartObject)
                        {
                            throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
                        }

                        object value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue);

                        reader.ReadAndAssert();
                        return value;
                    }
                    break;
                }
                case JsonContractType.Dictionary:
                {
                    JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)contract;
                    object targetDictionary;

                    if (existingValue == null)
                    {
                        bool createdFromNonDefaultCreator;
                        IDictionary dictionary = CreateNewDictionary(reader, dictionaryContract, out createdFromNonDefaultCreator);

                        if (createdFromNonDefaultCreator)
                        {
                            if (id != null)
                            {
                                throw JsonSerializationException.Create(reader, "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                            }

                            if (contract.OnSerializingCallbacks.Count > 0)
                            {
                                throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                            }

                            if (contract.OnErrorCallbacks.Count > 0)
                            {
                                throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                            }

                            if (!dictionaryContract.HasParameterizedCreatorInternal)
                            {
                                throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                            }
                        }

                        PopulateDictionary(dictionary, reader, dictionaryContract, member, id);

                        if (createdFromNonDefaultCreator)
                        {
                            ObjectConstructor<object> creator = dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator;

                            return creator(dictionary);
                        }
                        else if (dictionary is IWrappedDictionary)
                        {
                            return ((IWrappedDictionary)dictionary).UnderlyingDictionary;
                        }

                        targetDictionary = dictionary;
                    }
                    else
                    {
                        targetDictionary = PopulateDictionary(dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary)existingValue, reader, dictionaryContract, member, id);
                    }

                    return targetDictionary;
                }
            #if !(NET35 || NET20 || PORTABLE40)
                case JsonContractType.Dynamic:
                    JsonDynamicContract dynamicContract = (JsonDynamicContract)contract;
                    return CreateDynamic(reader, dynamicContract, member, id);
            #endif
            #if !(DOTNET || PORTABLE40 || PORTABLE)
                case JsonContractType.Serializable:
                    JsonISerializableContract serializableContract = (JsonISerializableContract)contract;
                    return CreateISerializable(reader, serializableContract, member, id);
            #endif
            }

            string message = @"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine +
                             @"To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." + Environment.NewLine;
            message = message.FormatWith(CultureInfo.InvariantCulture, resolvedObjectType, GetExpectedDescription(contract));

            throw JsonSerializationException.Create(reader, message);
        }
        private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape)
        {
            string propertyName;

            if (contract.ContractType == JsonContractType.Primitive)
            {
                JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
                if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable)
                {
                    DateTime dt = DateTimeUtils.EnsureDateTime((DateTime)name, writer.DateTimeZoneHandling);

                    escape = false;
                    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
                    DateTimeUtils.WriteDateTimeString(sw, dt, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
                    return sw.ToString();
                }
#if !NET20
                else if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffset || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffsetNullable)
                {
                    escape = false;
                    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
                    DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
                    return sw.ToString();
                }
#endif
                else
                {
                    escape = true;
                    return Convert.ToString(name, CultureInfo.InvariantCulture);
                }
            }
            else if (TryConvertToString(name, name.GetType(), out propertyName))
            {
                escape = true;
                return propertyName;
            }
            else
            {
                escape = true;
                return name.ToString();
            }
        }