-Added JsonDataExtensionAttribute
This commit is contained in:
@@ -75,4 +75,4 @@ using System.Security;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("4.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("5.0.4.16028")]
|
||||
[assembly: AssemblyFileVersion("5.0.4.16030")]
|
||||
|
||||
@@ -134,6 +134,173 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
}
|
||||
|
||||
public class ExtensionDataTestClass
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("custom_name")]
|
||||
public string CustomName { get; set; }
|
||||
[JsonIgnore]
|
||||
public IList<int> Ignored { get; set; }
|
||||
public bool GetPrivate { get; internal set; }
|
||||
public bool GetOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public readonly string Readonly = "Readonly";
|
||||
public IList<int> Ints { get; set; }
|
||||
|
||||
[JsonExtensionData]
|
||||
internal IDictionary<string, JToken> ExtensionData { get; set; }
|
||||
|
||||
public ExtensionDataTestClass()
|
||||
{
|
||||
Ints = new List<int> { 0 };
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtensionDataTest()
|
||||
{
|
||||
string json = @"{
|
||||
""Ints"": [1,2,3],
|
||||
""Ignored"": [1,2,3],
|
||||
""Readonly"": ""Readonly"",
|
||||
""Name"": ""Actually set!"",
|
||||
""CustomName"": ""Wrong name!"",
|
||||
""GetPrivate"": true,
|
||||
""GetOnly"": true,
|
||||
""NewValueSimple"": true,
|
||||
""NewValueComplex"": [1,2,3]
|
||||
}";
|
||||
|
||||
ExtensionDataTestClass c = JsonConvert.DeserializeObject<ExtensionDataTestClass>(json);
|
||||
|
||||
Assert.AreEqual("Actually set!", c.Name);
|
||||
Assert.AreEqual(4, c.Ints.Count);
|
||||
|
||||
Assert.AreEqual("Readonly", (string)c.ExtensionData["Readonly"]);
|
||||
Assert.AreEqual("Wrong name!", (string)c.ExtensionData["CustomName"]);
|
||||
Assert.AreEqual(true, (bool)c.ExtensionData["GetPrivate"]);
|
||||
Assert.AreEqual(true, (bool)c.ExtensionData["GetOnly"]);
|
||||
Assert.AreEqual(true, (bool)c.ExtensionData["NewValueSimple"]);
|
||||
Assert.IsTrue(JToken.DeepEquals(new JArray(1, 2, 3), c.ExtensionData["NewValueComplex"]));
|
||||
Assert.IsTrue(JToken.DeepEquals(new JArray(1, 2, 3), c.ExtensionData["Ignored"]));
|
||||
|
||||
Assert.AreEqual(7, c.ExtensionData.Count);
|
||||
}
|
||||
|
||||
public class MultipleExtensionDataAttributesTestClass
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[JsonExtensionData]
|
||||
internal IDictionary<string, JToken> ExtensionData1 { get; set; }
|
||||
[JsonExtensionData]
|
||||
internal IDictionary<string, JToken> ExtensionData2 { get; set; }
|
||||
}
|
||||
|
||||
public class ExtensionDataAttributesInheritanceTestClass : MultipleExtensionDataAttributesTestClass
|
||||
{
|
||||
[JsonExtensionData]
|
||||
internal IDictionary<string, JToken> ExtensionData0 { get; set; }
|
||||
}
|
||||
|
||||
public class FieldExtensionDataAttributeTestClass
|
||||
{
|
||||
[JsonExtensionData]
|
||||
internal IDictionary<object, object> ExtensionData;
|
||||
}
|
||||
|
||||
public class PublicExtensionDataAttributeTestClass
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[JsonExtensionData]
|
||||
public IDictionary<object, object> ExtensionData;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializePublicExtensionData()
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(new PublicExtensionDataAttributeTestClass
|
||||
{
|
||||
Name = "Name!",
|
||||
ExtensionData = new Dictionary<object, object>
|
||||
{
|
||||
{ "Test", 1 }
|
||||
}
|
||||
});
|
||||
|
||||
Assert.AreEqual(@"{""Name"":""Name!""}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializePublicExtensionData()
|
||||
{
|
||||
string json = @"{
|
||||
'Name':'Name!',
|
||||
'NoMatch':'NoMatch!',
|
||||
'ExtensionData':{'HAI':true}
|
||||
}";
|
||||
|
||||
var c = JsonConvert.DeserializeObject<PublicExtensionDataAttributeTestClass>(json);
|
||||
|
||||
Assert.AreEqual("Name!", c.Name);
|
||||
Assert.AreEqual(2, c.ExtensionData.Count);
|
||||
|
||||
Assert.AreEqual("NoMatch!", (string)(JValue)c.ExtensionData["NoMatch"]);
|
||||
|
||||
// the ExtensionData property is put into the extension data
|
||||
// inception
|
||||
var o = (JObject)c.ExtensionData["ExtensionData"];
|
||||
Assert.AreEqual(1, o.Count);
|
||||
Assert.IsTrue(JToken.DeepEquals(new JObject { { "HAI", true } }, o));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldExtensionDataAttributeTest_Serialize()
|
||||
{
|
||||
FieldExtensionDataAttributeTestClass c = new FieldExtensionDataAttributeTestClass
|
||||
{
|
||||
ExtensionData = new Dictionary<object, object>()
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(c);
|
||||
|
||||
Assert.AreEqual("{}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FieldExtensionDataAttributeTest_Deserialize()
|
||||
{
|
||||
var c = JsonConvert.DeserializeObject<FieldExtensionDataAttributeTestClass>("{'first':1,'second':2}");
|
||||
|
||||
Assert.AreEqual(2, c.ExtensionData.Count);
|
||||
Assert.AreEqual(1, (int)(JToken)c.ExtensionData["first"]);
|
||||
Assert.AreEqual(2, (int)(JToken)c.ExtensionData["second"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleExtensionDataAttributesTest()
|
||||
{
|
||||
var c = JsonConvert.DeserializeObject<MultipleExtensionDataAttributesTestClass>("{'first':1,'second':2}");
|
||||
|
||||
Assert.AreEqual(null, c.ExtensionData1);
|
||||
Assert.AreEqual(2, c.ExtensionData2.Count);
|
||||
Assert.AreEqual(1, (int)c.ExtensionData2["first"]);
|
||||
Assert.AreEqual(2, (int)c.ExtensionData2["second"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtensionDataAttributesInheritanceTest()
|
||||
{
|
||||
var c = JsonConvert.DeserializeObject<ExtensionDataAttributesInheritanceTestClass>("{'first':1,'second':2}");
|
||||
|
||||
Assert.AreEqual(null, c.ExtensionData1);
|
||||
Assert.AreEqual(null, c.ExtensionData2);
|
||||
Assert.AreEqual(2, c.ExtensionData0.Count);
|
||||
Assert.AreEqual(1, (int)c.ExtensionData0["first"]);
|
||||
Assert.AreEqual(2, (int)c.ExtensionData0["second"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenericCollectionInheritance()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Instructs the <see cref="JsonSerializer"/> to populate properties with no matching class member onto the specified collection.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class JsonExtensionDataAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -484,6 +484,7 @@ namespace Newtonsoft.Json
|
||||
/// </returns>
|
||||
public static JsonSerializer CreateDefault()
|
||||
{
|
||||
// copy static to local variable to avoid concurrency issues
|
||||
Func<JsonSerializerSettings> defaultSettingsCreator = JsonConvert.DefaultSettings;
|
||||
JsonSerializerSettings defaultSettings = (defaultSettingsCreator != null) ? defaultSettingsCreator() : null;
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="SerializationBinder.cs" />
|
||||
|
||||
@@ -114,6 +114,7 @@
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyDescriptor.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
<Compile Include="DateTimeZoneHandling.cs" />
|
||||
<Compile Include="Formatting.cs" />
|
||||
<Compile Include="JsonConstructorAttribute.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
<Compile Include="Linq\JPropertyKeyedCollection.cs" />
|
||||
<Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<Compile Include="JsonConverterCollection.cs" />
|
||||
<Compile Include="JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonIgnoreAttribute.cs" />
|
||||
<Compile Include="JsonObjectAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<Compile Include="JsonConverterCollection.cs" />
|
||||
<Compile Include="JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonIgnoreAttribute.cs" />
|
||||
<Compile Include="JsonObjectAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
<Compile Include="JsonConverterCollection.cs" />
|
||||
<Compile Include="JsonDictionaryAttribute.cs" />
|
||||
<Compile Include="JsonException.cs" />
|
||||
<Compile Include="JsonExtensionDataAttribute.cs" />
|
||||
<Compile Include="JsonIgnoreAttribute.cs" />
|
||||
<Compile Include="JsonObjectAttribute.cs" />
|
||||
<Compile Include="JsonPosition.cs" />
|
||||
|
||||
@@ -92,6 +92,6 @@ using System.Security;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("4.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("5.0.4.16028")]
|
||||
[assembly: AssemblyFileVersion("5.0.4.16030")]
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
@@ -389,9 +389,75 @@ namespace Newtonsoft.Json.Serialization
|
||||
contract.ConstructorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties));
|
||||
}
|
||||
}
|
||||
|
||||
contract.ExtensionDataSetter = GetExtensionDataForType(contract.NonNullableUnderlyingType);
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
private ExtensionDataSetter GetExtensionDataForType(Type type)
|
||||
{
|
||||
ExtensionDataSetter extensionDataSetter = null;
|
||||
|
||||
foreach (Type baseType in GetClassHierarchyForType(type))
|
||||
{
|
||||
IList<MemberInfo> members = new List<MemberInfo>();
|
||||
members.AddRange(baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
members.AddRange(baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
|
||||
foreach (MemberInfo member in members)
|
||||
{
|
||||
MemberTypes memberType = member.MemberType();
|
||||
if (memberType != MemberTypes.Property && memberType != MemberTypes.Field)
|
||||
continue;
|
||||
|
||||
// last instance of attribute wins on type if there are multiple
|
||||
if (!member.IsDefined(typeof(JsonExtensionDataAttribute), false))
|
||||
continue;
|
||||
|
||||
Type t = ReflectionUtils.GetMemberUnderlyingType(member);
|
||||
|
||||
Type dictionaryType;
|
||||
if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out dictionaryType))
|
||||
{
|
||||
Type keyType = dictionaryType.GetGenericArguments()[0];
|
||||
Type valueType = dictionaryType.GetGenericArguments()[1];
|
||||
|
||||
// change type to a class if it is the base interface so it can be instantiated if needed
|
||||
if (ReflectionUtils.IsGenericDefinition(t, typeof(IDictionary<,>)))
|
||||
t = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
|
||||
|
||||
if (keyType.IsAssignableFrom(typeof(string)) && valueType.IsAssignableFrom(typeof(JToken)))
|
||||
{
|
||||
MethodInfo addMethod = t.GetMethod("Add", new [] { keyType, valueType });
|
||||
Func<object, object> getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(member);
|
||||
Action<object, object> setExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(member);
|
||||
Func<object> createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(t);
|
||||
MethodCall<object, object> setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(addMethod);
|
||||
|
||||
extensionDataSetter = (o, key, value) =>
|
||||
{
|
||||
object dictionary = getExtensionDataDictionary(o);
|
||||
if (dictionary == null)
|
||||
{
|
||||
dictionary = createExtensionDataDictionary();
|
||||
setExtensionDataDictionary(o, dictionary);
|
||||
}
|
||||
|
||||
setExtensionDataDictionaryValue(dictionary, key, value);
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary<string, JToken>.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(member.DeclaringType), member.Name));
|
||||
}
|
||||
}
|
||||
|
||||
return extensionDataSetter;
|
||||
}
|
||||
|
||||
private ConstructorInfo GetAttributeConstructor(Type objectType)
|
||||
{
|
||||
IList<ConstructorInfo> markedConstructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).ToList();
|
||||
@@ -593,8 +659,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
foreach (Type baseType in GetClassHierarchyForType(type))
|
||||
{
|
||||
// while we allow more than one OnSerialized total, only one can be defined
|
||||
// per class
|
||||
// while we allow more than one OnSerialized total, only one can be defined per class
|
||||
MethodInfo currentOnSerializing = null;
|
||||
MethodInfo currentOnSerialized = null;
|
||||
MethodInfo currentOnDeserializing = null;
|
||||
@@ -1020,6 +1085,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
bool hasJsonIgnoreAttribute =
|
||||
JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null
|
||||
// automatically ignore extension data dictionary property if it is public
|
||||
|| JsonTypeReflector.GetAttribute<JsonExtensionDataAttribute>(attributeProvider) != null
|
||||
#if !(SILVERLIGHT || NETFX_CORE || PORTABLE40 || PORTABLE)
|
||||
|| JsonTypeReflector.GetAttribute<NonSerializedAttribute>(attributeProvider) != null
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Serialization
|
||||
@@ -63,6 +64,14 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <param name="errorContext">The error context.</param>
|
||||
public delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext);
|
||||
|
||||
/// <summary>
|
||||
/// Sets extension data for an object during deserialization.
|
||||
/// </summary>
|
||||
/// <param name="o">The object to set extension data on.</param>
|
||||
/// <param name="key">The extension data key.</param>
|
||||
/// <param name="value">The extension data value.</param>
|
||||
public delegate void ExtensionDataSetter(object o, string key, JToken value);
|
||||
|
||||
/// <summary>
|
||||
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -76,6 +76,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <value>The parametrized constructor.</value>
|
||||
public ConstructorInfo ParametrizedConstructor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the extension data setter.
|
||||
/// </summary>
|
||||
public ExtensionDataSetter ExtensionDataSetter { get; set; }
|
||||
|
||||
private bool? _hasRequiredOrDefaultValueProperties;
|
||||
internal bool HasRequiredOrDefaultValueProperties
|
||||
{
|
||||
|
||||
@@ -719,7 +719,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
return value;
|
||||
}
|
||||
|
||||
private void SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target)
|
||||
private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target)
|
||||
{
|
||||
object currentValue;
|
||||
bool useExistingValue;
|
||||
@@ -727,7 +727,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
bool gottenCurrentValue;
|
||||
|
||||
if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out useExistingValue, out currentValue, out propertyContract, out gottenCurrentValue))
|
||||
return;
|
||||
return false;
|
||||
|
||||
object value;
|
||||
|
||||
@@ -758,7 +758,12 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
|
||||
property.SetIsSpecified(target, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// the value wasn't set be JSON was populated onto the existing value
|
||||
return useExistingValue;
|
||||
}
|
||||
|
||||
private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue)
|
||||
@@ -769,10 +774,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
gottenCurrentValue = false;
|
||||
|
||||
if (property.Ignored)
|
||||
{
|
||||
reader.Skip();
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonToken tokenType = reader.TokenType;
|
||||
|
||||
@@ -798,26 +800,17 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
}
|
||||
|
||||
if (!property.Writable && !useExistingValue)
|
||||
{
|
||||
reader.Skip();
|
||||
return true;
|
||||
}
|
||||
|
||||
// test tokentype here because null might not be convertable to some types, e.g. ignoring null when applied to DateTime
|
||||
if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && tokenType == JsonToken.Null)
|
||||
{
|
||||
reader.Skip();
|
||||
return true;
|
||||
}
|
||||
|
||||
// test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime
|
||||
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
|
||||
&& JsonReader.IsPrimitiveToken(tokenType)
|
||||
&& MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue()))
|
||||
{
|
||||
reader.Skip();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentValue == null)
|
||||
{
|
||||
@@ -1367,7 +1360,8 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
|
||||
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, null, null);
|
||||
|
||||
SetPropertyValue(property, propertyConverter, null, member, reader, newObject);
|
||||
if (!SetPropertyValue(property, propertyConverter, null, member, reader, newObject))
|
||||
reader.Skip();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1700,7 +1694,10 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
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();
|
||||
if (!reader.Read())
|
||||
break;
|
||||
|
||||
SetExtensionData(contract, reader, memberName, newObject);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1714,7 +1711,9 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
|
||||
SetPropertyPresence(reader, property, propertiesPresence);
|
||||
|
||||
SetPropertyValue(property, propertyConverter, contract, member, reader, newObject);
|
||||
// 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)
|
||||
{
|
||||
@@ -1745,6 +1744,27 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
return newObject;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private void EndObject(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
|
||||
{
|
||||
if (propertiesPresence != null)
|
||||
|
||||
@@ -80,7 +80,13 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
|
||||
if (method is MethodInfo)
|
||||
callExpression = EnsureCastExpression(callExpression, type);
|
||||
{
|
||||
MethodInfo m = (MethodInfo)method;
|
||||
if (m.ReturnType != typeof(void))
|
||||
callExpression = EnsureCastExpression(callExpression, type);
|
||||
else
|
||||
callExpression = Expression.Block(callExpression, Expression.Constant(null));
|
||||
}
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(MethodCall<T, object>), callExpression, targetParameterExpression, argsParameterExpression);
|
||||
|
||||
|
||||
@@ -348,7 +348,11 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static IEnumerable<PropertyInfo> GetProperties(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetPropertiesRecursive().Where(p => TestAccessibility(p, bindingFlags));
|
||||
IList<PropertyInfo> properties = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
|
||||
? type.GetTypeInfo().DeclaredProperties.ToList()
|
||||
: type.GetTypeInfo().GetPropertiesRecursive();
|
||||
|
||||
return properties.Where(p => TestAccessibility(p, bindingFlags));
|
||||
}
|
||||
|
||||
private static IList<MemberInfo> GetMembersRecursive(this TypeInfo type)
|
||||
@@ -424,7 +428,11 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static IEnumerable<FieldInfo> GetFields(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetFieldsRecursive().Where(f => TestAccessibility(f, bindingFlags)).ToList();
|
||||
IList<FieldInfo> fields = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
|
||||
? type.GetTypeInfo().DeclaredFields.ToList()
|
||||
: type.GetTypeInfo().GetFieldsRecursive();
|
||||
|
||||
return fields.Where(f => TestAccessibility(f, bindingFlags)).ToList();
|
||||
}
|
||||
|
||||
private static bool TestAccessibility(PropertyInfo member, BindingFlags bindingFlags)
|
||||
|
||||
Reference in New Issue
Block a user