public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object list;

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

            //read into the 'Data' path
            var preDataPath = ReaderUtil.ReadUntilStart(reader, DataPathRegex);

            //we should be dealing with list types, but we also want the element type
            Type elementType;

            if (!ListUtil.IsList(objectType, out elementType))
            {
                throw new ArgumentException($"{typeof(ResourceObjectListConverter)} can only read json lists", nameof(objectType));
            }

            var itemsIterator = ReaderUtil.IterateList(reader).Select(x => serializer.Deserialize(reader, elementType));

            list = ListUtil.CreateList(objectType, itemsIterator);

            //read out of the 'Data' path
            ReaderUtil.ReadUntilEnd(reader, preDataPath);

            return(list);
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DocumentRootConverter.TryResolveAsRootData(writer, value, serializer))
            {
                return;
            }

            //if they have custom convertors registered, we will respect them
            var customConvertor = serializer.Converters.FirstOrDefault(x => x.CanWrite && x.CanConvert(value.GetType()));

            if (customConvertor != null && customConvertor != this)
            {
                customConvertor.WriteJson(writer, value, serializer);
                return;
            }

            var isRelationship = RelationshipPathRegex.IsMatch(writer.Path);

            if (isRelationship)
            {
                WriteReferenceObjectJson(writer, value, serializer);
            }
            else
            {
                WriteFullObjectJson(writer, value, serializer);
            }
        }
        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 void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DocumentRootConverter.TryResolveAsRootData(writer, value, serializer))
            {
                return;
            }

            var isRelationship = RelationshipPathRegex.IsMatch(writer.Path);

            if (isRelationship)
            {
                WriteReferenceObjectJson(writer, value, serializer);
            }
            else
            {
                WriteFullObjectJson(writer, value, serializer);
            }
        }
Beispiel #5
0
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DocumentRootConverter.TryResolveAsRootData(writer, value, serializer))
            {
                return;
            }

            WriterUtil.WriteIntoElement(writer, DataPathRegex, PropertyNames.Data, () =>
            {
                var enumerable = value as IEnumerable <object> ?? Enumerable.Empty <object>();
                writer.WriteStartArray();
                foreach (var valueElement in enumerable)
                {
                    serializer.Serialize(writer, valueElement);
                }
                writer.WriteEndArray();
            });
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DocumentRootConverter.TryResolveAsRootData(writer, value, serializer))
            {
                return;
            }

            WriterUtil.WriteIntoElement(writer, DataWritePathRegex, PropertyNames.Data, () =>
            {
                var probe = writer as AttributeOrRelationshipProbe;
                if (probe != null)
                {
                    //if someone is sending a probe its because we are in a relationship property.
                    //let the probe know we are in a relationship and write the reference element
                    probe.PropertyType = AttributeOrRelationshipProbe.Type.Relationship;
                    WriteReferenceObjectJson(writer, value, serializer);
                }
                else
                {
                    WriteFullObjectJson(writer, value, serializer);
                }
            });
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DocumentRootConverter.TryResolveAsRootData(writer, value, serializer))
            {
                return;
            }

            var contractResolver = serializer.ContractResolver;
            var enumerable       = value as IEnumerable <object> ?? Enumerable.Empty <object>();

            writer.WriteStartArray();
            foreach (var valueElement in enumerable)
            {
                if (valueElement == null || !(contractResolver.ResolveContract(valueElement.GetType()).Converter is ResourceObjectConverter))
                {
                    throw new JsonApiFormatException(writer.Path,
                                                     $"Expected to find to find resource objects within lists, but found '{valueElement}'",
                                                     "Resource indentifier objects MUST contain 'id' members");
                }
                serializer.Serialize(writer, valueElement);
            }
            writer.WriteEndArray();
        }
        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
            if (DocumentRootConverter.TryResolveAsRootData(reader, objectType, serializer, out object obj))
            {
                return(obj);
            }

            //read into the 'Data' element
            return(ReaderUtil.ReadInto(
                       reader as ForkableJsonReader ?? new ForkableJsonReader(reader),
                       DataReadPathRegex,
                       dataReader =>
            {
                //if they have custom convertors registered, we will respect them
                var customConvertor = serializer.Converters.FirstOrDefault(x => x.CanRead && x.CanConvert(objectType));
                if (customConvertor != null && customConvertor != this)
                {
                    return customConvertor.ReadJson(reader, objectType, existingValue, serializer);
                }

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

                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 = CreateObject(objectType, reference.Type, serializer);
                        serializationData.Included.Add(reference, existingValue);
                    }
                    if (existingValue is JObject existingValueJObject)
                    {
                        //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(existingValueJObject.CreateReader(), dataReader.SerializationDataToken);
                        dataReader.Read(); //JObject readers begin at Not Started
                        existingValue = CreateObject(objectType, reference.Type, serializer);
                        serializationData.Included[reference] = existingValue;
                    }
                }

                //additional check to ensure the object we created is of the correct type
                if (!TypeInfoShim.IsInstanceOf(objectType.GetTypeInfo(), existingValue))
                {
                    throw new JsonSerializationException($"Unable to assign object '{existingValue}' to type '{objectType}'");
                }

                PopulateProperties(serializer, existingValue, dataReader);
                return existingValue;
            }));
        }