-Added support for setting readonly fields when marked up with JsonPropertyAttribute

This commit is contained in:
JamesNK
2011-08-01 23:50:20 +00:00
parent e65e371e1d
commit a1f59aff82
5 changed files with 63 additions and 8 deletions
@@ -41,5 +41,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.2.14001")]
[assembly: AssemblyFileVersion("4.0.2.14002")]
#endif
@@ -4641,5 +4641,48 @@ keyword such as type of business.""
""BaseClassValue"": ""BaseClassValue!""
}", json);
}
public class PrivateMembersClassWithAttributes
{
public PrivateMembersClassWithAttributes(string privateString, string internalString, string readonlyString)
{
_privateString = privateString;
_readonlyString = readonlyString;
_internalString = internalString;
}
public PrivateMembersClassWithAttributes()
{
_readonlyString = "default!";
}
[JsonProperty]
private string _privateString;
[JsonProperty]
private readonly string _readonlyString;
[JsonProperty]
internal string _internalString;
public string UseValue()
{
return _readonlyString;
}
}
[Test]
public void PrivateMembersClassWithAttributesTest()
{
PrivateMembersClassWithAttributes c1 = new PrivateMembersClassWithAttributes("privateString!", "internalString!", "readonlyString!");
string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
Assert.AreEqual(@"{
""_privateString"": ""privateString!"",
""_readonlyString"": ""readonlyString!"",
""_internalString"": ""internalString!""
}", json);
PrivateMembersClassWithAttributes c2 = JsonConvert.DeserializeObject<PrivateMembersClassWithAttributes>(json);
Assert.AreEqual("readonlyString!", c2.UseValue());
}
}
}
@@ -110,7 +110,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.2.14001")]
[assembly: AssemblyFileVersion("4.0.2.14002")]
#endif
[assembly: CLSCompliant(true)]
@@ -367,7 +367,8 @@ namespace Newtonsoft.Json.Serialization
property.PropertyType = parameterInfo.ParameterType;
bool allowNonPublicAccess;
SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out allowNonPublicAccess);
bool hasExplicitAttribute;
SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out allowNonPublicAccess, out hasExplicitAttribute);
property.Readable = false;
property.Writable = true;
@@ -783,10 +784,11 @@ namespace Newtonsoft.Json.Serialization
property.ValueProvider = CreateMemberValueProvider(member);
bool allowNonPublicAccess;
SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out allowNonPublicAccess);
bool hasExplicitAttribute;
SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out allowNonPublicAccess, out hasExplicitAttribute);
property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess);
property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, hasExplicitAttribute);
property.ShouldSerialize = CreateShouldSerializeTest(member);
SetIsSpecifiedActions(property, member);
@@ -794,8 +796,10 @@ namespace Newtonsoft.Json.Serialization
return property;
}
private void SetPropertySettingsFromAttributes(JsonProperty property, ICustomAttributeProvider attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess)
private void SetPropertySettingsFromAttributes(JsonProperty property, ICustomAttributeProvider attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess, out bool hasExplicitAttribute)
{
hasExplicitAttribute = false;
#if !PocketPC && !NET20
DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType);
@@ -807,6 +811,9 @@ namespace Newtonsoft.Json.Serialization
#endif
JsonPropertyAttribute propertyAttribute = JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(attributeProvider);
if (propertyAttribute != null)
hasExplicitAttribute = true;
bool hasIgnoreAttribute = (JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null);
string mappedName;
@@ -859,9 +866,13 @@ namespace Newtonsoft.Json.Serialization
allowNonPublicAccess = true;
if (propertyAttribute != null)
allowNonPublicAccess = true;
#if !PocketPC && !NET20
if (dataMemberAttribute != null)
{
allowNonPublicAccess = true;
hasExplicitAttribute = true;
}
#endif
}
@@ -626,17 +626,18 @@ namespace Newtonsoft.Json.Utilities
/// </summary>
/// <param name="member">The MemberInfo to determine whether can be set.</param>
/// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
/// <param name="canSetReadOnly">if set to <c>true</c> then allow the member to be set if read-only.</param>
/// <returns>
/// <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
/// </returns>
public static bool CanSetMemberValue(MemberInfo member, bool nonPublic)
public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly)
{
switch (member.MemberType)
{
case MemberTypes.Field:
FieldInfo fieldInfo = (FieldInfo)member;
if (fieldInfo.IsInitOnly)
if (fieldInfo.IsInitOnly && !canSetReadOnly)
return false;
if (nonPublic)
return true;