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 (beforeClosingObject != null)
				beforeClosingObject(value, writer);

			writer.WriteEndObject();

			_serializeStack.RemoveAt(_serializeStack.Count - 1);

			OnSerialized(writer, contract, value);
		}
    private void EndObject(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
    {
      if (propertiesPresence != null)
      {
        foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
        {
          JsonProperty property = propertyPresence.Key;
          PropertyPresence presence = propertyPresence.Value;

          if (presence == PropertyPresence.None || presence == PropertyPresence.Null)
          {
            try
            {
              Required resolvedRequired = property._required ?? contract.ItemRequired ?? Required.Default;

              switch (presence)
              {
                case PropertyPresence.None:
                  if (resolvedRequired == Required.AllowNull || resolvedRequired == Required.Always)
                    throw JsonSerializationException.Create(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 (resolvedRequired == Required.Always)
                    throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
                  break;
              }
            }
            catch (Exception ex)
            {
              if (IsErrorHandled(newObject, contract, property.PropertyName, reader.Path, ex))
                HandleError(reader, true, initialDepth);
              else
                throw;
            }
          }
        }
      }
    }
        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);
                        }
                    }
                }
            }

            if (beforeClosingObject != null)
                beforeClosingObject(value, writer);

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, value);
        }
    public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultConstructor)
    {
      object newObject = null;

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

      if (objectContract.OverrideConstructor != null)
      {
        if (objectContract.OverrideConstructor.GetParameters().Length > 0)
        {
          createdFromNonDefaultConstructor = true;
          return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.OverrideConstructor, id);
        }

        newObject = objectContract.OverrideConstructor.Invoke(null);
      }
      else if (objectContract.DefaultCreator != null &&
        (!objectContract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedConstructor == null))
      {
        // use the default constructor if it is...
        // public
        // non-public and the user has change constructor handling settings
        // non-public and there is no other constructor
        newObject = objectContract.DefaultCreator();
      }
      else if (objectContract.ParametrizedConstructor != null)
      {
        createdFromNonDefaultConstructor = true;
        return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedConstructor, id);
      }

      if (newObject == null)
        throw JsonSerializationException.Create(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, objectContract.UnderlyingType));

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

      // only need to keep a track of properies presence if they are required or a value should be defaulted if missing
      Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer.DefaultValueHandling, DefaultValueHandling.Populate))
        ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None)
        : null;

      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 JsonSerializationException.Create(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, contract, member);

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

                SetPropertyPresence(reader, property, propertiesPresence);

                SetPropertyValue(property, propertyConverter, contract, member, reader, newObject);
              }
              catch (Exception ex)
              {
                if (IsErrorHandled(newObject, contract, memberName, reader.Path, ex))
                  HandleError(reader, true, initialDepth);
                else
                  throw;
              }
            }
            break;
          case JsonToken.EndObject:
            {
              EndObject(newObject, reader, contract, initialDepth, propertiesPresence);

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

      throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
    }
    private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
    {
      ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");

      Type objectType = contract.UnderlyingType;

      IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, 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 = (JsonArrayContract)propertyContract;

            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 = (JsonDictionaryContract)propertyContract;

            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 IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, 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, contract, containerProperty);

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

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

                object propertyValue;
                if (propertyConverter != null && propertyConverter.CanRead)
                  propertyValue = propertyConverter.ReadJson(reader, property.PropertyType, null, GetInternalSerializer());
                else
                  propertyValue = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null);

                propertyValues[property] = propertyValue;
              }
              else
              {
                reader.Skip();
              }
            }
            else
            {
              if (!reader.Read())
                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

              if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
                throw JsonSerializationException.Create(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 JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
        }
      } while (!exit && reader.Read());

      return propertyValues;
    }
Example #8
0
        private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
        {
            OnSerializing(writer, contract, value);

            _serializeStack.Add(value);

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

            int initialDepth = writer.Top;

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

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

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

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

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

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

                            writer.WritePropertyName(propertyName);

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

            if (beforeClosingObject != null)
            {
                beforeClosingObject(value, writer);
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, value);
        }
Example #9
0
    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 void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o)
        {
            if (contract.ExtensionDataSetter != null)
            {
                try
                {
                    JToken extensionDataValue = JToken.ReadFrom(reader);
                    //object value = CreateValueInternal(reader, null, null, null, contract, member, null);

                    contract.ExtensionDataSetter(o, memberName, extensionDataValue);
                }
                catch (Exception ex)
                {
                    throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex);
                }
            }
            else
            {
                reader.Skip();
            }
        }
    private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id)
    {
      OnDeserializing(reader, contract, newObject);

      // only need to keep a track of properies presence if they are required or a value should be defaulted if missing
      Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer.DefaultValueHandling, DefaultValueHandling.Populate))
        ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None)
        : null;

      if (id != null)
        AddReference(reader, id, newObject);

      int initialDepth = reader.Depth;

      bool finished = false;
      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 (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                    TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);

                  if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
                    throw JsonSerializationException.Create(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, contract, member);

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

                SetPropertyPresence(reader, property, propertiesPresence);

                SetPropertyValue(property, propertyConverter, contract, member, reader, newObject);
              }
              catch (Exception ex)
              {
	              var newEx = new JsonSerializationException("Could not read value for property: " + memberName, ex);
				  TryClearErrorContext();
	              if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, newEx))
		              HandleError(reader, true, initialDepth);
	              else
		              throw newEx;
              }
            }
            break;
          case JsonToken.EndObject:
            finished = true;
            break;
          case JsonToken.Comment:
            // ignore
            break;
          default:
            throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
        }
      } while (!finished && reader.Read());

      if (!finished)
        ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");

      EndObject(newObject, reader, contract, initialDepth, propertiesPresence);

      OnDeserialized(reader, contract, newObject);
      return newObject;
    }
        private IDictionary<JsonProperty, object> ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType, out IDictionary<string, object> extensionData)
        {
            extensionData = (contract.ExtensionDataSetter != null) ? new Dictionary<string, object>() : null;

            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.CreatorParameters.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, contract, containerProperty);

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

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

                                object propertyValue;
                                if (propertyConverter != null && propertyConverter.CanRead)
                                    propertyValue = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null);
                                else
                                    propertyValue = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null);

                                propertyValues[property] = propertyValue;
                                continue;
                            }
                        }
                        else
                        {
                            if (!reader.Read())
                                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

                            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
                                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);

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

                        if (extensionData != null)
                        {
                            object value = CreateValueInternal(reader, null, null, null, contract, containerProperty, null);
                            extensionData[memberName] = value;
                        }
                        else
                        {
                            reader.Skip();
                        }
                        break;
                    case JsonToken.Comment:
                        break;
                    case JsonToken.EndObject:
                        exit = true;
                        break;
                    default:
                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
                }
            } while (!exit && reader.Read());

            return propertyValues;
        }
        private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor<object> creator, string id)
        {
            ValidationUtils.ArgumentNotNull(creator, "creator");

            // only need to keep a track of properies presence if they are required or a value should be defaulted if missing
            Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate))
                ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None)
                : null;

            Type objectType = contract.UnderlyingType;

            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
            {
                string parameters = string.Join(", ", contract.CreatorParameters.Select(p => p.PropertyName).ToArray());
                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, parameters)), null);
            }

            IDictionary<string, object> extensionData;
            IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, objectType, out extensionData);

            object[] creatorParameterValues = new object[contract.CreatorParameters.Count];
            IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();

            foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
            {
                JsonProperty property = propertyValue.Key;

                JsonProperty matchingCreatorParameter;
                if (contract.CreatorParameters.Contains(property))
                {
                    matchingCreatorParameter = property;
                }
                else
                {
                    // check to see if a parameter with the same name as the underlying property name exists and match to that
                    matchingCreatorParameter = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName, property.UnderlyingName);
                }

                if (matchingCreatorParameter != null)
                {
                    int i = contract.CreatorParameters.IndexOf(matchingCreatorParameter);
                    creatorParameterValues[i] = propertyValue.Value;
                }
                else
                {
                    remainingPropertyValues.Add(propertyValue);
                }

                if (propertiesPresence != null)
                {
                    // map from creator property to normal property
                    JsonProperty presenceProperty = propertiesPresence.Keys.FirstOrDefault(p => p.PropertyName == property.PropertyName);
                    if (presenceProperty != null)
                        propertiesPresence[presenceProperty] = (propertyValue.Value == null) ? PropertyPresence.Null : PropertyPresence.Value;
                }
            }

            // handle giving default values to creator parameters
            // this needs to happen before the call to creator
            if (propertiesPresence != null)
            {
                foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
                {
                    JsonProperty property = propertyPresence.Key;
                    PropertyPresence presence = propertyPresence.Value;

                    if (!property.Ignored && (presence == PropertyPresence.None || presence == PropertyPresence.Null))
                    {
                        if (property.PropertyContract == null)
                            property.PropertyContract = GetContractSafe(property.PropertyType);

                        if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate))
                        {
                            // have to use the name because property presence doesn't use creator properties
                            int i = contract.CreatorParameters.IndexOf(p => p.PropertyName == property.PropertyName);

                            if (i != -1)
                            {
                                creatorParameterValues[i] = EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType);
                            }
                        }
                    }
                }
            }

            object createdObject = creator(creatorParameterValues);

            if (id != null)
                AddReference(reader, id, createdObject);

            OnDeserializing(reader, contract, createdObject);

            // 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(property, 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 = (JsonArrayContract)propertyContract;

                        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 dictionaryContract = (JsonDictionaryContract)propertyContract;

                        object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
                        if (createdObjectDictionary != null)
                        {
                            IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
                            IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;

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

            if (extensionData != null)
            {
                foreach (KeyValuePair<string, object> e in extensionData)
                {
                    contract.ExtensionDataSetter(createdObject, e.Key, e.Value);
                }
            }

            EndObject(createdObject, reader, contract, reader.Depth, propertiesPresence);

            OnDeserialized(reader, contract, createdObject);
            return createdObject;
        }
    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);
    }
Example #15
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 object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
    {
      ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");

      Type objectType = contract.UnderlyingType;

      if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
        TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);

      IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, 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)
        AddReference(reader, id, createdObject);

      OnDeserializing(reader, contract, createdObject);

      // 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 = (JsonArrayContract)propertyContract;

            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 dictionaryContract = (JsonDictionaryContract)propertyContract;

            object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
            if (createdObjectDictionary != null)
            {
              IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary) createdObjectDictionary;
              IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary) value;

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

      OnDeserialized(reader, contract, createdObject);
      return createdObject;
    }