コード例 #1
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;
                }
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, value);
        }
コード例 #2
0
        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.GetResolvedDefaultValue(), 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 as IJsonLineInfo, reader.Path, ex))
                                HandleError(reader, true, initialDepth);
                            else
                                throw;
                        }
                    }
                }
            }
        }
コード例 #3
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;
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        private void SetExtensionData(JsonObjectContract contract, JsonReader reader, string memberName, object o)
        {
            if (contract.ExtensionDataSetter != null)
            {
                try
                {
                    JToken extensionDataValue = JToken.ReadFrom(reader);

                    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();
            }
        }
コード例 #6
0
        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 = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null);
                                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 (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));

                            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;
        }
コード例 #7
0
        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));

                                    if (!reader.Read())
                                        break;

                                    SetExtensionData(contract, reader, memberName, newObject);
                                    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);

                                // set extension data if property is ignored or readonly
                                if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject))
                                    SetExtensionData(contract, reader, memberName, newObject);
                            }
                            catch (Exception ex)
                            {
                                if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, ex))
                                    HandleError(reader, true, initialDepth);
                                else
                                    throw;
                            }
                        }
                        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;
        }
コード例 #8
0
        public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultConstructor)
        {
            object newObject = null;

            if (!objectContract.IsInstantiable)
                throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".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;
        }