public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            //we may be starting the deserialization here, if thats the case we need to resolve this object as the root
            object obj;

            if (DocumentRootConverter.TryResolveAsRootData(reader, objectType, serializer, out obj))
            {
                return(obj);
            }


            //read into the 'Data' element
            return(ReaderUtil.ReadInto(
                       reader as ForkableJsonReader ?? new ForkableJsonReader(reader),
                       DataReadPathRegex,
                       dataReader =>
            {
                //if the value has been explicitly set to null then the value of the element is simply null
                if (dataReader.TokenType == JsonToken.Null)
                {
                    return null;
                }

                JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
                var serializationData = SerializationData.GetSerializationData(dataReader);

                //if we arent given an existing value check the references to see if we have one in there
                //if we dont have one there then create a new object to populate
                if (existingValue == null)
                {
                    var reference = ReaderUtil.ReadAheadToIdentifyObject(dataReader);

                    if (!serializationData.Included.TryGetValue(reference, out existingValue))
                    {
                        existingValue = contract.DefaultCreator();
                        serializationData.Included.Add(reference, existingValue);
                    }
                    if (existingValue is JObject)
                    {
                        //sometimes the value in the reference resolver is a JObject. This occurs when we
                        //did not know what type it should be when we first read it (i.e. included was processed
                        //before the item). In these cases we will create a new object and read data from the JObject
                        dataReader = new ForkableJsonReader(((JObject)existingValue).CreateReader(), dataReader.SerializationDataToken);
                        dataReader.Read(); //JObject readers begin at Not Started
                        existingValue = contract.DefaultCreator();
                        serializationData.Included[reference] = existingValue;
                    }
                }

                PopulateProperties(serializer, existingValue, dataReader, contract);
                return existingValue;
            }));
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            //we may be starting the deserialization here, if thats the case we need to resolve this object as the root
            object obj;

            if (DocumentRootConverter.TryResolveAsRootData(reader, objectType, serializer, out obj))
            {
                return(obj);
            }

            JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
            var isNew = false;

            if (existingValue == null)
            {
                existingValue = contract.DefaultCreator();
                isNew         = true;
            }

            existingValue = PopulateProperties(serializer, existingValue, reader, contract);
            if (isNew)
            {
                var id       = contract.Properties.GetClosestMatchProperty(PropertyNames.Id).ValueProvider.GetValue(existingValue);
                var type     = existingValue.GetType().Name.ToLower();
                var typeProp = contract.Properties.GetClosestMatchProperty(PropertyNames.Type);
                if (typeProp != null)
                {
                    type = typeProp.ValueProvider.GetValue(existingValue).ToString();
                }

                serializer.ReferenceResolver.AddReference(null, type + ":" + id, existingValue);
            }
            return(existingValue);
        }
Exemplo n.º 3
0
        private object ReadObject(JsonReader reader, JsonObjectContract objectContract, JsonSerializer serializer)
        {
            var token      = (JObject)JToken.ReadFrom(reader);
            var objectType = objectContract.UnderlyingType;

            if (IsTypeExplicitlyDefined(token, serializer.SerializationBinder, ref objectType))
            {
                reader = token.CreateReader();
                return(ReadJson(reader, objectType, null, serializer));
            }
            else
            {
                if (objectContract.UnderlyingType.IsAbstract)
                {
                    throw new InvalidOperationException();
                }

                if (entityCache.GetEntity(token, objectContract.UnderlyingType, out var id) is object value)
                {
                    serializer.Populate(token.CreateReader(), value);
                    return(value);
                }

                if (objectContract.OverrideCreator is not null)
                {
                    throw new NotImplementedException();
                }
                else if (objectContract.DefaultCreator is not null)
                {
                    value = objectContract.DefaultCreator();
                    serializer.Populate(token.CreateReader(), value);
                }
                else
                {
                    throw new NotImplementedException();
                }

                if (id is not null)
                {
                    entityCache.PutEntity(id, value);
                }

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

            if (objectContract.OverrideCreator != null)
            {
                if (objectContract.CreatorParameters.Count > 0)
                {
                    createdFromNonDefaultCreator = true;
                    return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id);
                }

                newObject = objectContract.OverrideCreator(new object[0]);
            }
            else if (objectContract.DefaultCreator != null &&
                     (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedCreator == 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 creator
                newObject = objectContract.DefaultCreator();
            }
            else if (objectContract.ParametrizedCreator != null)
            {
                createdFromNonDefaultCreator = true;
                return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id);
            }

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

            createdFromNonDefaultCreator = false;
            return newObject;
        }
        private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id)
        {
            object newObject = null;

              if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract)
            throw new JsonSerializationException("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.DefaultCreator != null &&
            (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
              {
            newObject = contract.DefaultCreator();
              }

              if (newObject != null)
              {
            PopulateObject(newObject, reader, contract, id);
            return newObject;
              }

              return CreateObjectFromNonDefaultConstructor(reader, contract, id);
        }