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