private void SetRequiredProperty(JsonReader reader, JsonProperty property, Dictionary<JsonProperty, RequiredValue> requiredProperties)
 {
     if (property != null)
       {
     requiredProperties[property] = (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined)
       ? RequiredValue.Null
       : RequiredValue.Value;
       }
 }
        private bool ShouldSetPropertyValue(JsonProperty property, object value)
        {
            if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && value == null)
            return false;

              if (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) == DefaultValueHandling.Ignore && Equals(value, property.DefaultValue))
            return false;

              if (!property.Writable)
            return false;

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

              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 (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) == DefaultValueHandling.Ignore
            && JsonReader.IsPrimitiveToken(reader.TokenType)
            && Equals(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);
        }
        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)
              throw new JsonSerializationException("JSON reference {0} property must have a string value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));

            string reference = reader.Value.ToString();

            CheckedRead(reader);
            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(reference);
              }
              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.ToString();
            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);
              }

            #if !SILVERLIGHT && !PocketPC
              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 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, 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, 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, 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 WriteMemberInfoProperty(JsonWriter writer, object memberValue, JsonProperty property, JsonContract contract)
        {
            string propertyName = property.PropertyName;
              object defaultValue = property.DefaultValue;

              if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore &&
              memberValue == null)
            return;

              if (property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling) ==
              DefaultValueHandling.Ignore && Equals(memberValue, defaultValue))
            return;

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

              if (!CheckForCircularReference(memberValue, property.ReferenceLoopHandling, contract))
            return;

              if (memberValue == null && property.Required == Required.Always)
            throw new JsonSerializationException("Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));

              writer.WritePropertyName(propertyName);
              SerializeValue(writer, memberValue, contract, property, null);
        }
        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)
              value = CreateAndPopulateList(reader, reference, arrayContract);
            else
              value = PopulateList(arrayContract.CreateWrapper(existingValue), reader, reference, arrayContract);
              }
              else
              {
            value = CreateJToken(reader, contract);
              }
              return value;
        }
        private bool ShouldWriteReference(object value, JsonProperty property, JsonContract contract)
        {
            if (value == null)
            return false;
              if (contract is JsonPrimitiveContract)
            return false;

              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)
            isReference = contract.IsReference;

              if (isReference == null)
              {
            if (contract is JsonArrayContract)
              isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
            else
              isReference = HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Objects);
              }

              if (!isReference.Value)
            return false;

              return Serializer.ReferenceResolver.IsReferenced(value);
        }
        //private bool ShouldWriteTypeProperty(JsonProperty member, JsonContract contract, TypeNameHandling typeFlag)
        //{
        //  if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeFlag))
        //    return true;
        //  if ((((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto)
        //      || (member != null
        //          && (member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto
        //          && contract.UnderlyingType != member.PropertyType)
        //      )
        //}
        private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContract collectionValueContract)
        {
            if (HasFlag(((member != null) ? member.TypeNameHandling : null) ?? Serializer.TypeNameHandling, typeNameHandlingFlag))
            return true;

              if (member != null)
              {
            if ((member.TypeNameHandling ?? Serializer.TypeNameHandling) == TypeNameHandling.Auto && contract.UnderlyingType != member.PropertyType)
              return true;
              }
              else if (collectionValueContract != null)
              {
            if (Serializer.TypeNameHandling == TypeNameHandling.Auto && contract.UnderlyingType != collectionValueContract.UnderlyingType)
              return true;
              }

              return false;
        }
        private bool ShouldSerialize(JsonProperty property, object target)
        {
            if (property.ShouldSerialize == null)
            return true;

              return property.ShouldSerialize(target);
        }
        private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContract collectionValueContract)
        {
            JsonConverter converter = (member != null) ? member.Converter : null;

              if (value == null)
              {
            writer.WriteNull();
            return;
              }

              if ((converter != null
              || ((converter = valueContract.Converter) != null)
              || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
              || ((converter = valueContract.InternalConverter) != null))
            && converter.CanWrite)
              {
            SerializeConvertable(writer, converter, value, valueContract);
              }
              else if (valueContract is JsonPrimitiveContract)
              {
            writer.WriteValue(value);
              }
              else if (valueContract is JsonStringContract)
              {
            SerializeString(writer, value, (JsonStringContract) valueContract);
              }
              else if (valueContract is JsonObjectContract)
              {
            SerializeObject(writer, value, (JsonObjectContract)valueContract, member, collectionValueContract);
              }
              else if (valueContract is JsonDictionaryContract)
              {
            JsonDictionaryContract dictionaryContract = (JsonDictionaryContract) valueContract;
            SerializeDictionary(writer, dictionaryContract.CreateWrapper(value), dictionaryContract, member, collectionValueContract);
              }
              else if (valueContract is JsonArrayContract)
              {
            if (value is IList)
            {
              SerializeList(writer, (IList)value, (JsonArrayContract)valueContract, member, collectionValueContract);
            }
            else if (value is IEnumerable)
            {
              SerializeList(writer, ((IEnumerable)value).Cast<object>().ToList(), (JsonArrayContract)valueContract, member, collectionValueContract);
            }
            else
            {
              throw new Exception(
            "Cannot serialize '{0}' into a JSON array. Type does not implement IEnumerable.".FormatWith(
              CultureInfo.InvariantCulture, value.GetType()));
            }
              }
              else if (valueContract is JsonLinqContract)
              {
            ((JToken)value).WriteTo(writer, (Serializer.Converters != null) ? Serializer.Converters.ToArray() : null);
              }
            #if !SILVERLIGHT && !PocketPC
              else if (valueContract is JsonISerializableContract)
              {
            SerializeISerializable(writer, (ISerializable) value, (JsonISerializableContract) valueContract);
              }
            #endif
        }
        private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContract collectionValueContract)
        {
            contract.InvokeOnSerializing(value, Serializer.Context);

              SerializeStack.Add(value);
              writer.WriteStartObject();

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

              int initialDepth = writer.Top;

              foreach (JsonProperty property in contract.Properties)
              {
            try
            {
              if (!property.Ignored && property.Readable && ShouldSerialize(property, value))
              {
            object memberValue = property.ValueProvider.GetValue(value);
            JsonContract memberContract = GetContractSafe(memberValue);

            WriteMemberInfoProperty(writer, memberValue, property, memberContract);
              }
            }
            catch (Exception ex)
            {
              if (IsErrorHandled(value, contract, property.PropertyName, ex))
            HandleError(writer, initialDepth);
              else
            throw;
            }
              }

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

              contract.InvokeOnSerialized(value, Serializer.Context);
        }
        private void SerializeList(JsonWriter writer, IList values, JsonArrayContract contract, JsonProperty member, JsonContract collectionValueContract)
        {
            contract.InvokeOnSerializing(values, Serializer.Context);

              SerializeStack.Add(values);

              bool isReference = contract.IsReference ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
              bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, collectionValueContract);

              if (isReference || includeTypeDetails)
              {
            writer.WriteStartObject();

            if (isReference)
            {
              writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
              writer.WriteValue(Serializer.ReferenceResolver.GetReference(values));
            }
            if (includeTypeDetails)
            {
              WriteTypeProperty(writer, values.GetType());
            }
            writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
              }

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

              writer.WriteStartArray();

              int initialDepth = writer.Top;

              for (int i = 0; i < values.Count; i++)
              {
            try
            {
              object value = values[i];
              JsonContract valueContract = GetContractSafe(value);

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

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

              writer.WriteEndArray();

              if (isReference || includeTypeDetails)
              {
            writer.WriteEndObject();
              }

              SerializeStack.RemoveAt(SerializeStack.Count - 1);

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

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