-Added support for serializing extension data

-Added support for reference loop handling and type name handling to extension data
-Bug fixes
This commit is contained in:
James Newton-King
2013-10-06 12:32:56 +13:00
parent 23cc86837e
commit 3536c76873
10 changed files with 434 additions and 69 deletions
@@ -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.6.16604")]
[assembly: AssemblyFileVersion("5.0.6.16606")]
@@ -534,6 +534,27 @@ namespace Newtonsoft.Json.Tests.Serialization
public IDictionary<object, object> ExtensionData;
}
public class PublicNoReadExtensionDataAttributeTestClass
{
public string Name { get; set; }
[JsonExtensionData(ReadData = false)]
public IDictionary<object, object> ExtensionData;
}
public class PublicNoWriteExtensionDataAttributeTestClass
{
public string Name { get; set; }
[JsonExtensionData(WriteData = false)]
public IDictionary<object, object> ExtensionData;
}
public class PublicJTokenExtensionDataAttributeTestClass
{
public string Name { get; set; }
[JsonExtensionData]
public IDictionary<string, JToken> ExtensionData;
}
[Test]
public void DeserializeDirectoryAccount()
{
@@ -558,9 +579,175 @@ namespace Newtonsoft.Json.Tests.Serialization
}
});
Assert.AreEqual(@"{""Name"":""Name!"",""Test"":1}", json);
}
[Test]
public void SerializePublicExtensionDataNull()
{
string json = JsonConvert.SerializeObject(new PublicExtensionDataAttributeTestClass
{
Name = "Name!"
});
Assert.AreEqual(@"{""Name"":""Name!""}", json);
}
[Test]
public void SerializePublicNoWriteExtensionData()
{
string json = JsonConvert.SerializeObject(new PublicNoWriteExtensionDataAttributeTestClass
{
Name = "Name!",
ExtensionData = new Dictionary<object, object>
{
{ "Test", 1 }
}
});
Assert.AreEqual(@"{""Name"":""Name!""}", json);
}
[Test]
public void DeserializeNoReadPublicExtensionData()
{
PublicNoReadExtensionDataAttributeTestClass c = JsonConvert.DeserializeObject<PublicNoReadExtensionDataAttributeTestClass>(@"{""Name"":""Name!"",""Test"":1}");
Assert.AreEqual(null, c.ExtensionData);
}
[Test]
public void SerializePublicExtensionDataCircularReference()
{
var c = new PublicExtensionDataAttributeTestClass
{
Name = "Name!",
ExtensionData = new Dictionary<object, object>
{
{ "Test", 1 }
}
};
c.ExtensionData["Self"] = c;
string json = JsonConvert.SerializeObject(c, new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
Formatting = Formatting.Indented
});
Assert.AreEqual(@"{
""$id"": ""1"",
""Name"": ""Name!"",
""Test"": 1,
""Self"": {
""$ref"": ""1""
}
}", json);
var c2 = JsonConvert.DeserializeObject<PublicExtensionDataAttributeTestClass>(json, new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All
});
Assert.AreEqual("Name!", c2.Name);
PublicExtensionDataAttributeTestClass bizzaroC2 = (PublicExtensionDataAttributeTestClass)c2.ExtensionData["Self"];
Assert.AreEqual(c2, bizzaroC2);
Assert.AreEqual(1, (long)bizzaroC2.ExtensionData["Test"]);
}
[Test]
public void DeserializePublicJTokenExtensionDataCircularReference()
{
string json = @"{
""$id"": ""1"",
""Name"": ""Name!"",
""Test"": 1,
""Self"": {
""$ref"": ""1""
}
}";
var c2 = JsonConvert.DeserializeObject<PublicJTokenExtensionDataAttributeTestClass>(json, new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All
});
Assert.AreEqual("Name!", c2.Name);
JObject bizzaroC2 = (JObject)c2.ExtensionData["Self"];
Assert.AreEqual("Name!", (string)bizzaroC2["Name"]);
Assert.AreEqual(1, (int)bizzaroC2["Test"]);
Assert.AreEqual(1, (int)c2.ExtensionData["Test"]);
}
[Test]
public void DeserializePublicExtensionDataTypeNamdHandling()
{
string json = @"{
""$id"": ""1"",
""Name"": ""Name!"",
""Test"": 1,
""Self"": {
""$type"": ""Newtonsoft.Json.Tests.TestObjects.WagePerson, Newtonsoft.Json.Tests"",
""HourlyWage"": 2.0,
""Name"": null,
""BirthDate"": ""0001-01-01T00:00:00"",
""LastModified"": ""0001-01-01T00:00:00""
}
}";
PublicExtensionDataAttributeTestClass c2 = JsonConvert.DeserializeObject<PublicExtensionDataAttributeTestClass>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
});
Assert.AreEqual("Name!", c2.Name);
WagePerson bizzaroC2 = (WagePerson)c2.ExtensionData["Self"];
Assert.AreEqual(2m, bizzaroC2.HourlyWage);
}
[Test]
public void SerializePublicExtensionDataTypeNamdHandling()
{
PublicExtensionDataAttributeTestClass c = new PublicExtensionDataAttributeTestClass
{
Name = "Name!",
ExtensionData = new Dictionary<object, object>
{
{
"Test", new WagePerson
{
HourlyWage = 2.1m
}
}
}
};
string json = JsonConvert.SerializeObject(c, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
Formatting = Formatting.Indented
});
Assert.AreEqual(@"{
""$type"": ""Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+PublicExtensionDataAttributeTestClass, Newtonsoft.Json.Tests"",
""Name"": ""Name!"",
""Test"": {
""$type"": ""Newtonsoft.Json.Tests.TestObjects.WagePerson, Newtonsoft.Json.Tests"",
""HourlyWage"": 2.1,
""Name"": null,
""BirthDate"": ""0001-01-01T00:00:00"",
""LastModified"": ""0001-01-01T00:00:00""
}
}", json);
}
[Test]
public void DeserializePublicExtensionData()
{
@@ -575,7 +762,7 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual("Name!", c.Name);
Assert.AreEqual(2, c.ExtensionData.Count);
Assert.AreEqual("NoMatch!", (string)(JValue)c.ExtensionData["NoMatch"]);
Assert.AreEqual("NoMatch!", (string)c.ExtensionData["NoMatch"]);
// the ExtensionData property is put into the extension data
// inception
@@ -603,19 +790,19 @@ namespace Newtonsoft.Json.Tests.Serialization
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"]);
Assert.AreEqual(1, (long)c.ExtensionData["first"]);
Assert.AreEqual(2, (long)c.ExtensionData["second"]);
}
[Test]
public void MultipleExtensionDataAttributesTest()
{
var c = JsonConvert.DeserializeObject<MultipleExtensionDataAttributesTestClass>("{'first':1,'second':2}");
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"]);
Assert.AreEqual(1, (int)((JArray)c.ExtensionData2["first"])[0]);
Assert.AreEqual(2, (int)((JArray)c.ExtensionData2["second"])[0]);
}
[Test]
@@ -9166,6 +9353,45 @@ Parameter name: value",
]", json);
}
public class Foo2
{
public string Name { get; set; }
}
[Test]
[Ignore]
public void SerializeMultipleObjectsFromStream()
{
StringReader sr = new StringReader(@"{ ""name"": ""bar"" }{ ""name"": ""baz"" }");
var reader1 = new JsonTextReader(sr);
var serializer1 = new JsonSerializer { };
var foo1 = serializer1.Deserialize<Foo2>(reader1);
Assert.AreEqual("bar", foo1.Name);
var reader2 = new JsonTextReader(sr);
var serializer2 = new JsonSerializer { };
var foo2 = serializer2.Deserialize<Foo2>(reader2);
Assert.AreEqual("baz", foo2.Name);
}
#if !(PORTABLE || PORTABLE40)
[Test]
public void SerializeDictionaryWithStructKey()
{
string json = JsonConvert.SerializeObject(
new Dictionary<Size, Size> { { new Size(1, 2), new Size(3, 4) } }
);
Assert.AreEqual(@"{""1, 2"":""3, 4""}", json);
Dictionary<Size, Size> d = JsonConvert.DeserializeObject<Dictionary<Size, Size>>(json);
Assert.AreEqual(new Size(1, 2), d.Keys.First());
Assert.AreEqual(new Size(3, 4), d.Values.First());
}
#endif
[Test]
public void DeserializeCustomReferenceResolver()
{
@@ -8,5 +8,13 @@ namespace Newtonsoft.Json
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public class JsonExtensionDataAttribute : Attribute
{
public bool WriteData { get; set; }
public bool ReadData { get; set; }
public JsonExtensionDataAttribute()
{
WriteData = true;
ReadData = true;
}
}
}
@@ -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.6.16604")]
[assembly: AssemblyFileVersion("5.0.6.16606")]
[assembly: CLSCompliant(true)]
@@ -391,32 +391,35 @@ namespace Newtonsoft.Json.Serialization
}
}
contract.ExtensionDataSetter = GetExtensionDataForType(contract.NonNullableUnderlyingType);
MemberInfo extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType);
if (extensionDataMember != null)
SetExtensionDataDelegates(contract, extensionDataMember);
return contract;
}
private ExtensionDataSetter GetExtensionDataForType(Type type)
private MemberInfo GetExtensionDataMemberForType(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)
IEnumerable<MemberInfo> members = GetClassHierarchyForType(type).SelectMany(baseType =>
{
MemberTypes memberType = member.MemberType();
IList<MemberInfo> m = new List<MemberInfo>();
m.AddRange(baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
m.AddRange(baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
return m;
});
MemberInfo extensionDataMember = members.LastOrDefault(m =>
{
MemberTypes memberType = m.MemberType();
if (memberType != MemberTypes.Property && memberType != MemberTypes.Field)
continue;
return false;
// last instance of attribute wins on type if there are multiple
if (!member.IsDefined(typeof(JsonExtensionDataAttribute), false))
continue;
if (!m.IsDefined(typeof(JsonExtensionDataAttribute), false))
return false;
Type t = ReflectionUtils.GetMemberUnderlyingType(member);
Type t = ReflectionUtils.GetMemberUnderlyingType(m);
Type dictionaryType;
if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out dictionaryType))
@@ -424,39 +427,122 @@ namespace Newtonsoft.Json.Serialization
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;
}
return true;
}
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));
}
throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary<string, JToken>.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name));
});
return extensionDataMember;
}
private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member)
{
JsonExtensionDataAttribute extensionDataAttribute = ReflectionUtils.GetAttribute<JsonExtensionDataAttribute>(member);
if (extensionDataAttribute == null)
return;
Type t = ReflectionUtils.GetMemberUnderlyingType(member);
Type dictionaryType;
ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out dictionaryType);
Type keyType = dictionaryType.GetGenericArguments()[0];
Type valueType = dictionaryType.GetGenericArguments()[1];
bool isJTokenValueType = typeof(JToken).IsAssignableFrom(valueType);
// 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);
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 extensionDataSetter = (o, key, value) =>
{
object dictionary = getExtensionDataDictionary(o);
if (dictionary == null)
{
dictionary = createExtensionDataDictionary();
setExtensionDataDictionary(o, dictionary);
}
// convert object value to JToken so it is compatible with dictionary
// could happen because of primitive types, type name handling and references
if (isJTokenValueType && !(value is JToken))
value = JToken.FromObject(value);
setExtensionDataDictionaryValue(dictionary, key, value);
};
Type enumerableWrapper = typeof(DictionaryEnumerator<,>).MakeGenericType(keyType, valueType);
ConstructorInfo constructors = enumerableWrapper.GetConstructors().First();
MethodCall<object, object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(constructors);
ExtensionDataGetter extensionDataGetter = o =>
{
object dictionary = getExtensionDataDictionary(o);
if (dictionary == null)
return null;
return (IEnumerable<KeyValuePair<object, object>>)createEnumerableWrapper(null, dictionary);
};
if (extensionDataAttribute.ReadData)
contract.ExtensionDataSetter = extensionDataSetter;
if (extensionDataAttribute.WriteData)
contract.ExtensionDataGetter = extensionDataGetter;
}
internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>, IEnumerator<KeyValuePair<object, object>>
{
private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
{
ValidationUtils.ArgumentNotNull(e, "e");
_e = e.GetEnumerator();
}
return extensionDataSetter;
public bool MoveNext()
{
return _e.MoveNext();
}
public void Reset()
{
_e.Reset();
}
public KeyValuePair<object, object> Current
{
get { return new KeyValuePair<object, object>(_e.Current.Key, _e.Current.Value); }
}
public void Dispose()
{
_e.Dispose();
}
object IEnumerator.Current
{
get { return Current; }
}
public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
}
private ConstructorInfo GetAttributeConstructor(Type objectType)
@@ -24,6 +24,7 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
@@ -70,7 +71,13 @@ namespace Newtonsoft.Json.Serialization
/// <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);
public delegate void ExtensionDataSetter(object o, string key, object value);
/// <summary>
/// Gets extension data for an object during serialization.
/// </summary>
/// <param name="o">The object to set extension data on.</param>
public delegate IEnumerable<KeyValuePair<object, object>> ExtensionDataGetter(object o);
/// <summary>
/// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
@@ -81,6 +81,11 @@ namespace Newtonsoft.Json.Serialization
/// </summary>
public ExtensionDataSetter ExtensionDataSetter { get; set; }
/// <summary>
/// Gets or sets the extension data getter.
/// </summary>
public ExtensionDataGetter ExtensionDataGetter { get; set; }
private bool? _hasRequiredOrDefaultValueProperties;
internal bool HasRequiredOrDefaultValueProperties
{
@@ -1733,7 +1733,7 @@ To fix this error either change the environment to be fully trusted, change the
if (!reader.Read())
break;
SetExtensionData(contract, reader, memberName, newObject);
SetExtensionData(contract, member, reader, memberName, newObject);
continue;
}
@@ -1749,7 +1749,7 @@ To fix this error either change the environment to be fully trusted, change the
// set extension data if property is ignored or readonly
if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject))
SetExtensionData(contract, reader, memberName, newObject);
SetExtensionData(contract, member, reader, memberName, newObject);
}
catch (Exception ex)
{
@@ -1780,15 +1780,15 @@ 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)
private void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o)
{
if (contract.ExtensionDataSetter != null)
{
try
{
JToken extensionDataValue = JToken.ReadFrom(reader);
object value = CreateValueInternal(reader, null, null, null, contract, member, null);
contract.ExtensionDataSetter(o, memberName, extensionDataValue);
contract.ExtensionDataSetter(o, memberName, value);
}
catch (Exception ex)
{
@@ -393,6 +393,37 @@ namespace Newtonsoft.Json.Serialization
}
}
if (contract.ExtensionDataGetter != null)
{
IEnumerable<KeyValuePair<object, object>> extensionData = contract.ExtensionDataGetter(value);
if (extensionData != null)
{
foreach (KeyValuePair<object, object> e in extensionData)
{
JsonContract keyContract = GetContractSafe(e.Key);
JsonContract valueContract = GetContractSafe(e.Value);
bool escape;
string propertyName = GetPropertyName(writer, e.Key, keyContract, out escape);
if (ShouldWriteReference(e.Value, null, valueContract, contract, member))
{
writer.WritePropertyName(propertyName);
WriteReference(writer, e.Value);
}
else
{
if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member))
continue;
writer.WritePropertyName(propertyName);
SerializeValue(writer, e.Value, valueContract, null, contract, member);
}
}
}
}
writer.WriteEndObject();
_serializeStack.RemoveAt(_serializeStack.Count - 1);
@@ -854,7 +885,7 @@ To fix this error either change the environment to be fully trusted, change the
foreach (DictionaryEntry entry in values)
{
bool escape;
string propertyName = GetPropertyName(writer, entry, contract.KeyContract, out escape);
string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);
propertyName = (contract.PropertyNameResolver != null)
? contract.PropertyNameResolver(propertyName)
@@ -896,20 +927,18 @@ To fix this error either change the environment to be fully trusted, change the
OnSerialized(writer, contract, underlyingDictionary);
}
private string GetPropertyName(JsonWriter writer, DictionaryEntry entry, JsonContract contract, out bool escape)
private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape)
{
object key = entry.Key;
string propertyName;
JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract;
if (primitiveContract != null)
if (contract.ContractType == JsonContractType.Primitive)
{
JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable)
{
escape = false;
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
DateTimeUtils.WriteDateTimeString(sw, (DateTime)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
DateTimeUtils.WriteDateTimeString(sw, (DateTime)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
return sw.ToString();
}
#if !NET20
@@ -917,17 +946,17 @@ To fix this error either change the environment to be fully trusted, change the
{
escape = false;
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
return sw.ToString();
}
#endif
else
{
escape = true;
return Convert.ToString(key, CultureInfo.InvariantCulture);
return Convert.ToString(name, CultureInfo.InvariantCulture);
}
}
else if (TryConvertToString(key, key.GetType(), out propertyName))
else if (TryConvertToString(name, name.GetType(), out propertyName))
{
escape = true;
return propertyName;
@@ -935,7 +964,7 @@ To fix this error either change the environment to be fully trusted, change the
else
{
escape = true;
return key.ToString();
return name.ToString();
}
}
@@ -87,6 +87,10 @@ namespace Newtonsoft.Json.Utilities
else
callExpression = Expression.Block(callExpression, Expression.Constant(null));
}
else
{
callExpression = EnsureCastExpression(callExpression, type);
}
LambdaExpression lambdaExpression = Expression.Lambda(typeof(MethodCall<T, object>), callExpression, targetParameterExpression, argsParameterExpression);