public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
		{
			if (jsonWriter == null)
				throw new ArgumentNullException("jsonWriter");

			if (objectType != null)
				_rootContract = Serializer._contractResolver.ResolveContract(objectType);

			SerializeValue(jsonWriter, value, GetContractSafe(value), null, null, null);
		}
        public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
        {
            if (jsonWriter == null)
                throw new ArgumentNullException("jsonWriter");

            _rootContract = (objectType != null) ? Serializer._contractResolver.ResolveContract(objectType) : null;
            _rootLevel = _serializeStack.Count + 1;

            _internalConverters = Serializer.Converters;

            JsonContract contract = GetContractSafe(value);

            try
            {
                if (ShouldWriteReference(value, null, contract, null, null))
                {
                    WriteReference(jsonWriter, value);
                }
                else
                {
                    SerializeValue(jsonWriter, value, contract, null, null, null);
                }
            }
            catch (Exception ex)
            {
                if (IsErrorHandled(null, contract, null, null, jsonWriter.Path, ex))
                {
                    HandleError(jsonWriter, 0);
                }
                else
                {
                    // clear context in case serializer is being used inside a converter
                    // if the converter wraps the error then not clearing the context will cause this error:
                    // "Current error context error is different to requested error."
                    ClearErrorContext();
                    throw;
                }
            }
            finally
            {
                // clear root contract to ensure that if level was > 1 then it won't
                // accidently be used for non root values
                _rootContract = null;
            }
        }
        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)
                {
                    escape = false;
                    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
                    DateTimeUtils.WriteDateTimeString(sw, (DateTime)name, 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();
            }
        }
    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)
      {
        reader.Skip();
        return true;
      }

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

      if ((objectCreationHandling == ObjectCreationHandling.Auto || objectCreationHandling == ObjectCreationHandling.Reuse)
          && (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)
          && property.Readable)
      {
        currentValue = property.ValueProvider.GetValue(target);
        gottenCurrentValue = true;

        useExistingValue = (currentValue != null
                            && !property.PropertyType.IsArray
                            && !ReflectionUtils.InheritsGenericDefinition(property.PropertyType, typeof (ReadOnlyCollection<>))
                            && !property.PropertyType.IsValueType());
      }

      if (!property.Writable && !useExistingValue)
      {
        reader.Skip();
        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 && reader.TokenType == JsonToken.Null)
      {
        reader.Skip();
        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)
          && JsonReader.IsPrimitiveToken(reader.TokenType)
          && MiscellaneousUtils.ValueEquals(reader.Value, property.DefaultValue))
      {
        reader.Skip();
        return true;
      }

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

      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 object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id)
    {
      object value;
      if (HasDefinedType(objectType))
      {
        JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract);

        if (existingValue == null)
        {
          bool isTemporaryListReference;
          IList list = CollectionUtils.CreateList(contract.CreatedType, out isTemporaryListReference);

          if (id != null && isTemporaryListReference)
            throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));

#if !PocketPC
          if (contract.OnSerializing != null && isTemporaryListReference)
            throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
#endif
          if (contract.OnError != null && isTemporaryListReference)
            throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));

          PopulateList(arrayContract.CreateWrapper(list), reader, arrayContract, member, id);

          // create readonly and fixed sized collections using the temporary list
          if (isTemporaryListReference)
          {
            if (contract.CreatedType.IsArray)
              list = CollectionUtils.ToArray(((List<object>)list).ToArray(), ReflectionUtils.GetCollectionItemType(contract.CreatedType));
            else if (ReflectionUtils.InheritsGenericDefinition(contract.CreatedType, typeof(ReadOnlyCollection<>)))
              list = (IList)ReflectionUtils.CreateInstance(contract.CreatedType, list);
          }
          else if (list is IWrappedCollection)
          {
            return ((IWrappedCollection)list).UnderlyingCollection;
          }

          value = list;
        }
        else
        {
          value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, arrayContract, member, id);
        }
      }
      else
      {
        value = CreateJToken(reader, contract);
      }
      return value;
    }
    private bool ReadSpecialProperties(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 'special' properties
          // $type, $id, $ref, etc
          bool specialProperty;

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

            if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal))
            {
              CheckedRead(reader);
              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;

              CheckedRead(reader);

              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.ReferenceResolver.ResolveReference(this, reference);
                  return true;
                }
              }
              else
              {
                specialProperty = true;
              }
            }
            else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal))
            {
              CheckedRead(reader);
              string qualifiedTypeName = reader.Value.ToString();

              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 (objectType != null
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
                    && 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);
              }

              CheckedRead(reader);

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

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

              CheckedRead(reader);
              specialProperty = true;
            }
            else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal))
            {
              CheckedRead(reader);
              object list = CreateList(reader, objectType, contract, member, existingValue, id);
              CheckedRead(reader);
              newValue = list;
              return true;
            }
            else
            {
              specialProperty = false;
            }
          } while (specialProperty
                   && reader.TokenType == JsonToken.PropertyName);
        }
      }
      return false;
    }
		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 (_rootContract != null && _serializeStack.Count == 1)
				{
					if (contract.UnderlyingType != _rootContract.CreatedType)
						return true;
				}
			}

			return false;
		}
		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);
					}

					return true;
				}
			}

			memberContract = null;
			memberValue = null;
			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 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.UnderlyingType.IsSealed()) ? property.PropertyContract : GetContractSafe(memberValue);

                if (ShouldWriteProperty(memberValue, property))
                {
                    if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
                    {
                        writer.WritePropertyName(property.PropertyName);
                        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);
                        }
                    }

                    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;
            }

            if (_serializeStack.IndexOf(value) != -1)
            {
                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 void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }

            JsonConverter converter;

            if ((((converter = (member != null) ? member.Converter : null) != null) ||
                 ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null) ||
                 ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null) ||
                 ((converter = valueContract.Converter) != null) ||
                 ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null) ||
                 ((converter = valueContract.InternalConverter) != 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, arrayContract.CreateWrapper(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, dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
                break;

#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
            case JsonContractType.Dynamic:
                SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
                break;
#endif
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
            case JsonContractType.Serializable:
                SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
                break;
#endif
            case JsonContractType.Linq:
                ((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
                break;
            }
        }
Exemple #13
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);

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

                _serializeStack.RemoveAt(_serializeStack.Count - 1);
            }
        }
Exemple #14
0
        private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            contract.InvokeOnSerializing(value, Serializer.Context);

            _serializeStack.Add(value);

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

            int initialDepth = writer.Top;

            foreach (JsonProperty property in contract.Properties)
            {
                try
                {
                    if (!property.Ignored && property.Readable && ShouldSerialize(property, value) && IsSpecified(property, value))
                    {
                        if (property.PropertyContract == null)
                        {
                            property.PropertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType);
                        }

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

                        if (ShouldWriteProperty(memberValue, property))
                        {
                            string propertyName = property.PropertyName;

                            if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
                            {
                                writer.WritePropertyName(propertyName);
                                WriteReference(writer, memberValue);
                                continue;
                            }

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

                            if (memberValue == null)
                            {
                                Required resolvedRequired = property._required ?? contract.ItemRequired ?? 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);
                                }
                            }

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

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            contract.InvokeOnSerialized(value, Serializer.Context);
        }
		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 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;

			if (_serializeStack.IndexOf(value) != -1)
			{
				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 void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, values.UnderlyingCollection);

            _serializeStack.Add(values.UnderlyingCollection);

            bool hasWrittenMetadataObject = WriteStartArray(writer, values.UnderlyingCollection, 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(values.UnderlyingCollection, 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, values.UnderlyingCollection);
        }
		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 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;

            foreach (JsonProperty property in contract.Properties)
            {
                // 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;
                        }

                        writer.WritePropertyName(property.PropertyName);
                        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 (value.TryGetMember(memberName, out memberValue))
                {
                    try
                    {
                        JsonContract valueContract = GetContractSafe(memberValue);

                        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);
        }
Exemple #20
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;
            }

            if (_serializeStack.IndexOf(value) != -1)
            {
                switch (referenceLoopHandling.GetValueOrDefault(Serializer.ReferenceLoopHandling))
                {
                case ReferenceLoopHandling.Error:
                    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());

                    throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);

                case ReferenceLoopHandling.Ignore:
                    return(false);

                case ReferenceLoopHandling.Serialize:
                    return(true);

                default:
                    throw new InvalidOperationException("Unexpected ReferenceLoopHandling value: '{0}'".FormatWith(CultureInfo.InvariantCulture, Serializer.ReferenceLoopHandling));
                }
            }

            return(true);
        }
        private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, values.UnderlyingDictionary);
            _serializeStack.Add(values.UnderlyingDictionary);

            WriteObjectStart(writer, values.UnderlyingDictionary, contract, member, collectionContract, containerProperty);

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

            int initialDepth = writer.Top;

            // Mono Unity 3.0 fix
            IWrappedDictionary d = values;

            foreach (DictionaryEntry entry in d)
            {
                string propertyName = GetPropertyName(entry);

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

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

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

                        writer.WritePropertyName(propertyName);

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

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, values.UnderlyingDictionary);
        }
    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)
        throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly.
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.
".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)));

      return arrayContract;
    }
        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;
        }
    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)
      {
        try
        {
          if (value == null && contract.IsNullable)
            return null;

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

              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, FormatValueForPrint(value), targetType), ex);
        }
      }

      return value;
    }
        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;
        }
Exemple #26
0
		private static void TrySimplifyingJson(RavenJObject jObject, JsonContract contract)
		{
			var objectContract = contract as JsonObjectContract;
			if (objectContract == null)
				return;

			var deferredActions = new List<Action>();
			foreach (var kvp in jObject)
			{
				var prop = kvp;
				if (prop.Value == null)
					continue;
				var obj = prop.Value as RavenJObject;
				if (obj == null)
					continue;

				var jsonProperty = objectContract.Properties.GetClosestMatchProperty(prop.Key);

				if (ShouldSimplifyJsonBasedOnType(obj.Value<string>("$type"), jsonProperty) == false)
					continue;

				if (obj.ContainsKey("$values") == false)
				{
					deferredActions.Add(() => obj.Remove("$type"));
				}
				else
				{
					deferredActions.Add(() => jObject[prop.Key] = obj["$values"]);
				}
			}
			foreach (var deferredAction in deferredActions)
			{
				deferredAction();
			}

			foreach (var prop in jObject.Where(prop => prop.Value != null))
			{
				switch (prop.Value.Type)
				{
					case JTokenType.Array:
						foreach (var item in ((RavenJArray)prop.Value))
						{
							var ravenJObject = item as RavenJObject;
							if (ravenJObject != null)
								TrySimplifyingJson(ravenJObject, contract);
						}
						break;
					case JTokenType.Object:
						TrySimplifyingJson((RavenJObject)prop.Value, contract);
						break;
				}
			}
		}
 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;
   }
 }
        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 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 void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
		{
			if (value == null)
			{
				writer.WriteNull();
				return;
			}

			JsonConverter converter;
			if ((((converter = (member != null) ? member.Converter : null) != null)
				 || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null)
				 || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null)
				 || ((converter = valueContract.Converter) != null)
				 || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
				 || ((converter = valueContract.InternalConverter) != 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 !(SILVERLIGHT || NETFX_CORE || 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 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:
          do
          {
            if (!reader.Read())
              return false;
          } while (reader.TokenType == JsonToken.Comment);

          return true;
        case ReadType.ReadAsInt32:
          reader.ReadAsInt32();
          break;
        case ReadType.ReadAsDecimal:
          reader.ReadAsDecimal();
          break;
        case ReadType.ReadAsBytes:
          reader.ReadAsBytes();
          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);
    }
		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.Value)
				return false;

			return Serializer.GetReferenceResolver().IsReferenced(this, value);
		}
    private JToken CreateJToken(JsonReader reader, JsonContract contract)
    {
      ValidationUtils.ArgumentNotNull(reader, "reader");

      if (contract != null && contract.UnderlyingType == typeof (JRaw))
      {
        return JRaw.Create(reader);
      }
      else
      {
        JToken token;
        using (JTokenWriter writer = new JTokenWriter())
        {
          writer.WriteToken(reader);
          token = writer.Token;
        }

        return token;
      }
    }
		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 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:
            // convert empty string to null automatically for nullable types
            if (string.IsNullOrEmpty((string)reader.Value) && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable)
              return null;

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

            return EnsureType(reader, reader.Value, 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 !(NETFX_CORE || 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.");
    }
		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);
			if (isReference)
			{
				WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
			}
			if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
			{
				WriteTypeProperty(writer, contract.UnderlyingType);
			}
		}
    internal string GetExpectedDescription(JsonContract contract)
    {
      switch (contract.ContractType)
      {
        case JsonContractType.Object:
        case JsonContractType.Dictionary:
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
        case JsonContractType.Serializable:
#endif
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
        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 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 object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
    {
      CheckedRead(reader);

      string id;
      object newValue;
      if (ReadSpecialProperties(reader, ref objectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
        return newValue;

      if (!HasDefinedType(objectType))
        return CreateJObject(reader);

      if (contract == null)
        throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType));

      switch (contract.ContractType)
      {
        case JsonContractType.Object:
          bool createdFromNonDefaultConstructor = false;
          JsonObjectContract objectContract = (JsonObjectContract) contract;
          object targetObject;
          if (existingValue != null)
            targetObject = existingValue;
          else
            targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultConstructor);

          // don't populate if read from non-default constructor because the object has already been read
          if (createdFromNonDefaultConstructor)
            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 (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
          {
            CheckedRead(reader);
            object value = CreateValueInternal(reader, objectType, primitiveContract, member, null, null, existingValue);

            CheckedRead(reader);
            return value;
          }
          break;
        case JsonContractType.Dictionary:
          JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) contract;
          object targetDictionary;
          if (existingValue != null)
            targetDictionary = existingValue;
          else
            targetDictionary = CreateNewDictionary(reader, dictionaryContract);

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

      throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly.
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.
".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)));
    }
		private string GetPropertyName(JsonWriter writer, DictionaryEntry entry, JsonContract contract, out bool escape)
		{
			object key = entry.Key;

			string propertyName;

			JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract;
			if (primitiveContract != null)
			{
				if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable)
				{
					escape = false;
					StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
					DateTimeUtils.WriteDateTimeString(sw, (DateTime)key, 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)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
					return sw.ToString();
				}
#endif
				else
				{
					escape = true;
					return Convert.ToString(key, CultureInfo.InvariantCulture);
				}
			}
			else if (TryConvertToString(key, key.GetType(), out propertyName))
			{
				escape = true;
				return propertyName;
			}
			else
			{
				escape = true;
				return key.ToString();
			}
		}
        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;
            IEnumerator enumerator;

            try
            {
                enumerator = values.GetEnumerator();
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Could not get enumerator for property: " + member, e);
            }
            using (enumerator as IDisposable)
            {
                while (true)
                {
                    try
                    {
                        if (enumerator.MoveNext() == false)
                        {
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException("Could not move to next value for property: " + member, e);
                    }
                    object value;
                    try
                    {
                        value = enumerator.Current;
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException("Could not get current value for property: " + member, e);
                    }
                    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);
        }