private void GenerateObjectSchema(Type type, JsonObjectContract contract)
    {
      CurrentSchema.Properties = new Dictionary<string, JsonSchema>();
      foreach (JsonProperty property in contract.Properties)
      {
        if (!property.Ignored)
        {
          bool optional = property.NullValueHandling == NullValueHandling.Ignore ||
                          HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) ||
                          property.ShouldSerialize != null ||
                          property.GetIsSpecified != null;

          JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required, !optional);

          if (property.DefaultValue != null)
            propertySchema.Default = JToken.FromObject(property.DefaultValue);

          CurrentSchema.Properties.Add(property.PropertyName, propertySchema);
        }
      }

      if (type.IsSealed)
        CurrentSchema.AllowAdditionalProperties = false;
    }
    private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, ConstructorInfo constructorInfo, string id)
    {
      ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");

      Type objectType = contract.UnderlyingType;

      IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, reader, objectType);

      IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object) null);
      IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();

      foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
      {
        ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.UnderlyingName).Key;
        if (matchingConstructorParameter != null)
          constructorParameters[matchingConstructorParameter] = propertyValue.Value;
        else
          remainingPropertyValues.Add(propertyValue);
      }

      object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());

      if (id != null)
        Serializer.ReferenceResolver.AddReference(this, id, createdObject);

      contract.InvokeOnDeserializing(createdObject, Serializer.Context);

      // go through unused values and set the newly created object's properties
      foreach (KeyValuePair<JsonProperty, object> remainingPropertyValue in remainingPropertyValues)
      {
        JsonProperty property = remainingPropertyValue.Key;
        object value = remainingPropertyValue.Value;

        if (ShouldSetPropertyValue(remainingPropertyValue.Key, remainingPropertyValue.Value))
        {
          property.ValueProvider.SetValue(createdObject, value);
        }
        else if (!property.Writable && value != null)
        {
          // handle readonly collection/dictionary properties
          JsonContract propertyContract = Serializer.ContractResolver.ResolveContract(property.PropertyType);

          if (propertyContract.ContractType == JsonContractType.Array)
          {
            JsonArrayContract propertyArrayContract = propertyContract as JsonArrayContract;

            object createdObjectCollection = property.ValueProvider.GetValue(createdObject);
            if (createdObjectCollection != null)
            {
              IWrappedCollection createdObjectCollectionWrapper = propertyArrayContract.CreateWrapper(createdObjectCollection);
              IWrappedCollection newValues = propertyArrayContract.CreateWrapper(value);

              foreach (object newValue in newValues)
              {
                createdObjectCollectionWrapper.Add(newValue);
              }
            }
          }
          else if (propertyContract.ContractType == JsonContractType.Dictionary)
          {
            JsonDictionaryContract jsonDictionaryContract = propertyContract as JsonDictionaryContract;

            object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
            if (createdObjectDictionary != null)
            {
              IWrappedDictionary createdObjectDictionaryWrapper = jsonDictionaryContract.CreateWrapper(createdObjectDictionary);
              IWrappedDictionary newValues = jsonDictionaryContract.CreateWrapper(value);

              foreach (DictionaryEntry newValue in newValues)
              {
                createdObjectDictionaryWrapper.Add(newValue.Key, newValue.Value);
              }
            }
          }
        }
      }

      contract.InvokeOnDeserialized(createdObject, Serializer.Context);
      return createdObject;
    }
    private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id)
    {
      object newObject = null;

      if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract)
        throw CreateSerializationException(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));

      if (contract.OverrideConstructor != null)
      {
        if (contract.OverrideConstructor.GetParameters().Length > 0)
          return CreateObjectFromNonDefaultConstructor(reader, contract, contract.OverrideConstructor, id);

        newObject = contract.OverrideConstructor.Invoke(null);
      }
      else if (contract.DefaultCreator != null &&
        (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
      {
        newObject = contract.DefaultCreator();
      }
      else if (contract.ParametrizedConstructor != null)
      {
        return CreateObjectFromNonDefaultConstructor(reader, contract, contract.ParametrizedConstructor, id);
      }

      if (newObject == null)
        throw CreateSerializationException(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));

      PopulateObject(newObject, reader, contract, id);
      return newObject;
    }
    private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id)
    {
      contract.InvokeOnDeserializing(newObject, Serializer.Context);

      Dictionary<JsonProperty, PropertyPresence> propertiesPresence =
        contract.Properties.ToDictionary(m => m, m => PropertyPresence.None);

      if (id != null)
        Serializer.ReferenceResolver.AddReference(this, id, newObject);

      int initialDepth = reader.Depth;

      do
      {
        switch (reader.TokenType)
        {
          case JsonToken.PropertyName:
            string memberName = reader.Value.ToString();

            try
            {
              // attempt exact case match first
              // then try match ignoring case
              JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);

              if (property == null)
              {
                if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
                  throw CreateSerializationException(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));

                reader.Skip();
                continue;
              }

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

              JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);

              if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
                throw CreateSerializationException(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

              SetPropertyPresence(reader, property, propertiesPresence);

              SetPropertyValue(property, propertyConverter, reader, newObject);
            }
            catch (Exception ex)
            {
              if (IsErrorHandled(newObject, contract, memberName, ex))
                HandleError(reader, initialDepth);
              else
                throw;
            }
            break;
          case JsonToken.EndObject:
            foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
            {
              JsonProperty property = propertyPresence.Key;
              PropertyPresence presence = propertyPresence.Value;

              switch (presence)
              {
                case PropertyPresence.None:
                  if (property.Required == Required.AllowNull || property.Required == Required.Always)
                    throw CreateSerializationException(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));

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

                  if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Populate)
                    && property.Writable)
                    property.ValueProvider.SetValue(newObject, EnsureType(reader, property.DefaultValue, CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType));
                  break;
                case PropertyPresence.Null:
                  if (property.Required == Required.Always)
                    throw CreateSerializationException(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
                  break;
              }
            }

            contract.InvokeOnDeserialized(newObject, Serializer.Context);
            return newObject;
          case JsonToken.Comment:
            // ignore
            break;
          default:
            throw CreateSerializationException(reader, "Unexpected token when deserializing object: " + reader.TokenType);
        }
      } while (reader.Read());

      throw CreateSerializationException(reader, "Unexpected end when deserializing object.");
    }
    private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonReader reader, Type objectType)
    {
      IDictionary<JsonProperty, object> propertyValues = new Dictionary<JsonProperty, object>();
      bool exit = false;
      do
      {
        switch (reader.TokenType)
        {
          case JsonToken.PropertyName:
            string memberName = reader.Value.ToString();

            // attempt exact case match first
            // then try match ignoring case
            JsonProperty property = contract.ConstructorParameters.GetClosestMatchProperty(memberName) ??
              contract.Properties.GetClosestMatchProperty(memberName);

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

              JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);

              if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
                throw CreateSerializationException(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

              if (!property.Ignored)
                propertyValues[property] = CreateValueProperty(reader, property, propertyConverter, null, true, null);
              else
                reader.Skip();
            }
            else
            {
              if (!reader.Read())
                throw CreateSerializationException(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

              if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
                throw CreateSerializationException(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name));

              reader.Skip();
            }
            break;
          case JsonToken.Comment:
            break;
          case JsonToken.EndObject:
            exit = true;
            break;
          default:
            throw CreateSerializationException(reader, "Unexpected token when deserializing object: " + reader.TokenType);
        }
      } while (!exit && reader.Read());

      return propertyValues;
    }
    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(this, 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) && 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);

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