private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    {
      if (contract.TypeCode == PrimitiveTypeCode.Bytes)
      {
        // if type name handling is enabled then wrap the base64 byte string in an object with the type name
        bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty);
        if (includeTypeDetails)
        {
          writer.WriteStartObject();
          WriteTypeProperty(writer, contract.CreatedType);
          writer.WritePropertyName(JsonTypeReflector.ValuePropertyName, false);

          JsonWriter.WriteValue(writer, contract.TypeCode, value);

          writer.WriteEndObject();
          return;
        }
      }

      JsonWriter.WriteValue(writer, contract.TypeCode, value);
    }
		private bool ShouldSerialize(JsonProperty property, object target)
		{
			if (property.ShouldSerialize == null)
				return true;

			return property.ShouldSerialize(target);
		}
		private void SetPropertyValue(JsonProperty property, JsonReader reader, object target)
		{
			if (property.Ignored)
			{
				reader.Skip();
				return;
			}

			object currentValue = null;
			bool useExistingValue = false;
			bool gottenCurrentValue = false;

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

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

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

			object existingValue = (useExistingValue) ? currentValue : null;
			object value = CreateValueProperty(reader, property, target, gottenCurrentValue, existingValue);

			// always set the value if useExistingValue is false,
			// otherwise also set it if CreateValue returns a new value compared to the currentValue
			// this could happen because of a JsonConverter against the type
			if ((!useExistingValue || value != currentValue)
			  && ShouldSetPropertyValue(property, value))
			{
				property.ValueProvider.SetValue(target, value);

				if (property.SetIsSpecified != null)
					property.SetIsSpecified(target, true);
			}
		}
		private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
		{
			CheckedRead(reader);

			string id = null;

			if (reader.TokenType == JsonToken.PropertyName)
			{
				bool specialProperty;

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

					if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal))
					{
						CheckedRead(reader);
						if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null)
							throw new JsonSerializationException("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 new JsonSerializationException("Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));

							return Serializer.ReferenceResolver.ResolveReference(this, reference);
						}
						else
						{
							specialProperty = true;
						}
					}
					else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal))
					{
						CheckedRead(reader);
						string qualifiedTypeName = reader.Value.ToString();

						CheckedRead(reader);

						if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) != 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 new JsonSerializationException("Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex);
							}

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

							if (objectType != null && !objectType.IsAssignableFrom(specifiedType))
								throw new JsonSerializationException("Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName));

							objectType = specifiedType;
							contract = GetContractSafe(specifiedType);
						}
						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);
						return list;
					}
					else
					{
						specialProperty = false;
					}
				} while (specialProperty
						 && reader.TokenType == JsonToken.PropertyName);
			}

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

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

			JsonDictionaryContract dictionaryContract = contract as JsonDictionaryContract;
			if (dictionaryContract != null)
			{
				if (existingValue == null)
					return CreateAndPopulateDictionary(reader, dictionaryContract, id);

				return PopulateDictionary(dictionaryContract.CreateWrapper(existingValue), reader, dictionaryContract, id);
			}

			JsonObjectContract objectContract = contract as JsonObjectContract;
			if (objectContract != null)
			{
				if (existingValue == null)
					return CreateAndPopulateObject(reader, objectContract, id);

				return PopulateObject(existingValue, reader, objectContract, id);
			}

			JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract;
			if (primitiveContract != null)
			{
				// 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, existingValue);

					CheckedRead(reader);
					return value;
				}
			}
#if !((UNITY_WINRT && !UNITY_EDITOR) || (UNITY_WP8 || UNITY_WP_8_1))
			JsonISerializableContract serializableContract = contract as JsonISerializableContract;
			if (serializableContract != null)
			{
				return CreateISerializable(reader, serializableContract, id);
			}
#endif

			throw new JsonSerializationException("Cannot deserialize JSON object into type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
		}
		private object CreateValueProperty(JsonReader reader, JsonProperty property, object target, bool gottenCurrentValue, object currentValue)
		{
			JsonContract contract = GetContractSafe(property.PropertyType, currentValue);
			Type objectType = property.PropertyType;

			JsonConverter converter = GetConverter(contract, property.MemberConverter);

			if (converter != null && converter.CanRead)
			{
				if (!gottenCurrentValue && target != null && property.Readable)
					currentValue = property.ValueProvider.GetValue(target);

				return converter.ReadJson(reader, objectType, currentValue, GetInternalSerializer());
			}

			return CreateValueInternal(reader, objectType, contract, property, currentValue);
		}
    private bool IsSpecified(JsonWriter writer, JsonProperty property, object target)
    {
      if (property.GetIsSpecified == null)
        return true;

      bool isSpecified = property.GetIsSpecified(target);

      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, isSpecified)), null);

      return isSpecified;
    }
    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 ShouldWriteProperty(object memberValue, JsonProperty property)
    {
      if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore &&
          memberValue == null)
        return false;

      if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
          && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue()))
        return false;

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

        var selfRef = (value is Vector2 || value is Vector3 || value is Vector4 || value is Color || value is Color32) 
			? ReferenceLoopHandling.Ignore 
			: referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling);

        switch (selfRef)
        {
          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? 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 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 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;
        case JsonContractType.Dynamic:
          SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
          break;
        case JsonContractType.Linq:
          ((JToken) value).WriteTo(writer, Serializer.Converters.ToArray());
          break;
      }
    }
		private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContract collectionValueContract)
		{
			if (contract.UnderlyingType == typeof(byte[]))
			{
				bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract);
				if (includeTypeDetails)
				{
					writer.WriteStartObject();
					WriteTypeProperty(writer, contract.CreatedType);
					writer.WritePropertyName(JsonTypeReflector.ValuePropertyName);
					writer.WriteValue(value);
					writer.WriteEndObject();
					return;
				}
			}

			writer.WriteValue(value);
		}
		private bool IsSpecified(JsonProperty property, object target)
		{
			if (property.GetIsSpecified == null)
				return true;

			return property.GetIsSpecified(target);
		}
    private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    {
      bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
      bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
      bool writeMetadataObject = isReference || includeTypeDetails;

      if (writeMetadataObject)
      {
        writer.WriteStartObject();

        if (isReference)
        {
          WriteReferenceIdProperty(writer, contract.UnderlyingType, values);
        }
        if (includeTypeDetails)
        {
          WriteTypeProperty(writer, values.GetType());
        }
        writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName, false);
      }

      if (contract.ItemContract == null)
        contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof (object));

      return writeMetadataObject;
    }
    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 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 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 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.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, 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 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);
      }
    }
    private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target)
    {
      if (property.ShouldSerialize == null)
        return true;

      bool shouldSerialize = property.ShouldSerialize(target);

      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, shouldSerialize)), null);

      return shouldSerialize;
    }
    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 SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary<JsonProperty, PropertyPresence> requiredProperties)
		{
			if (property != null)
			{
				requiredProperties[property] = (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined)
				  ? PropertyPresence.Null
				  : PropertyPresence.Value;
			}
		}
    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 object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
		{
			if (contract is JsonLinqContract)
				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, 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.Value, CultureInfo.InvariantCulture, objectType);
					case JsonToken.String:
						// convert empty string to null automatically for nullable types
						if (string.IsNullOrEmpty((string)reader.Value) &&
						  objectType != null &&
						  ReflectionUtils.IsNullableType(objectType))
							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.Value, CultureInfo.InvariantCulture, objectType);
					case JsonToken.StartConstructor:
					case JsonToken.EndConstructor:
						string constructorName = reader.Value.ToString();

						return constructorName;
					case JsonToken.Null:
					case JsonToken.Undefined:
						if (objectType == typeof(DBNull))
							return DBNull.Value;

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

			throw new JsonSerializationException("Unexpected end when deserializing object.");
		}
    private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    {
      OnSerializing(writer, contract, values);

      _serializeStack.Add(values);

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

      SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);

      if (hasWrittenMetadataObject)
        writer.WriteEndObject();

      _serializeStack.RemoveAt(_serializeStack.Count - 1);

      OnSerialized(writer, contract, values);
    }
		private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string reference)
		{
			object value;
			if (HasDefinedType(objectType))
			{
				JsonArrayContract arrayContract = EnsureArrayContract(objectType, contract);

				if (existingValue == null || objectType == typeof(BitArray))
					value = CreateAndPopulateList(reader, reference, arrayContract);
				else
					value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, reference, arrayContract);
			}
			else
			{
				value = CreateJToken(reader, contract);
			}
			return value;
		}
    private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices)
    {
      int dimension = indices.Length;
      int[] newIndices = new int[dimension + 1];
      for (int i = 0; i < dimension; i++)
      {
        newIndices[i] = indices[i];
      }

      writer.WriteStartArray();

      for (int i = 0; i < values.GetLength(dimension); i++)
      {
        newIndices[dimension] = i;
        bool isTopLevel = (newIndices.Length == values.Rank);

        if (isTopLevel)
        {
          object value = values.GetValue(newIndices);

          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, contract, i, null, writer.ContainerPath, ex))
              HandleError(writer, initialDepth + 1);
            else
              throw;
          }
        }
        else
        {
          SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices);
        }
      }

      writer.WriteEndArray();
    }
		private bool ShouldSetPropertyValue(JsonProperty property, object value)
		{
			if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && value == null)
				return false;

			if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore)
			  && MiscellaneousUtils.ValueEquals(value, property.DefaultValue))
				return false;

			if (!property.Writable)
				return false;

			return true;
		}
		private void SerializeDictionary(JsonWriter writer, IWrappedDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContract collectionValueContract)
		{
			contract.InvokeOnSerializing(values.UnderlyingDictionary, Serializer.Context);

			SerializeStack.Add(values.UnderlyingDictionary);
			writer.WriteStartObject();

			bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
			if (isReference)
			{
				writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
				writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingDictionary));
			}
			if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionValueContract))
			{
				WriteTypeProperty(writer, values.UnderlyingDictionary.GetType());
			}

			JsonContract childValuesContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));

			int initialDepth = writer.Top;

			// Mono Unity 3.0 fix
			IDictionary 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 = GetContractSafe(value);

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

						writer.WritePropertyName(propertyName);

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

			writer.WriteEndObject();
			SerializeStack.RemoveAt(SerializeStack.Count - 1);

			contract.InvokeOnSerialized(values.UnderlyingDictionary, Serializer.Context);
		}