implement a lookup of the fields/properties which should serialize null values

This commit is contained in:
Brendan Forster
2014-07-08 12:50:32 +09:30
parent 2e47369b9b
commit a19d2feb21
2 changed files with 44 additions and 14 deletions

View File

@@ -22,6 +22,9 @@ namespace Octokit.Internal
class GitHubSerializerStrategy : PocoJsonSerializerStrategy class GitHubSerializerStrategy : PocoJsonSerializerStrategy
{ {
readonly List<string> _membersWhichShouldPublishNull
= new List<string>();
protected override string MapClrMemberNameToJsonFieldName(string clrPropertyName) protected override string MapClrMemberNameToJsonFieldName(string clrPropertyName)
{ {
var rubyCased = clrPropertyName.ToRubyCase(); var rubyCased = clrPropertyName.ToRubyCase();
@@ -29,6 +32,41 @@ namespace Octokit.Internal
return rubyCased; return rubyCased;
} }
internal override IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
{
var fullName = type.FullName + "-";
// sometimes Octokit needs to send a null with the payload so the user
// can unset the value of a property.
// This method uses the same checks as PocoJsonSerializerStrategy
// to identify the right fields and properties to serialize
// but it then filters on the presence of SerializeNullAttribute.
foreach (var propertyInfo in ReflectionUtils.GetProperties(type))
{
if (!propertyInfo.CanRead)
continue;
var getMethod = ReflectionUtils.GetGetterMethodInfo(propertyInfo);
if (getMethod.IsStatic || !getMethod.IsPublic)
continue;
var attribute = propertyInfo.GetCustomAttribute<SerializeNullAttribute>();
if (attribute == null)
continue;
_membersWhichShouldPublishNull.Add(fullName + MapClrMemberNameToJsonFieldName(propertyInfo.Name));
}
foreach (var fieldInfo in ReflectionUtils.GetFields(type))
{
if (fieldInfo.IsStatic || !fieldInfo.IsPublic)
continue;
var attribute = fieldInfo.GetCustomAttribute<SerializeNullAttribute>();
if (attribute == null)
continue;
_membersWhichShouldPublishNull.Add(fullName + MapClrMemberNameToJsonFieldName(fieldInfo.Name));
}
return base.GetterValueFactory(type);
}
// This is overridden so that null values are omitted from serialized objects. // This is overridden so that null values are omitted from serialized objects.
[SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")] [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification = "Need to support .NET 2")]
protected override bool TrySerializeUnknownTypes(object input, out object output) protected override bool TrySerializeUnknownTypes(object input, out object output)
@@ -45,20 +83,9 @@ namespace Octokit.Internal
var value = getter.Value(input); var value = getter.Value(input);
if (value == null) if (value == null)
{ {
continue; var key = type.FullName + "-" + getter.Key;
if (!_membersWhichShouldPublishNull.Contains(key))
// sometimes Octokit needs to send a null continue;
// so look for this attribute when serializing
// XXX: we don't know which property we have at this point
// so this reflection trick doesn't work
// TODO: make this magic work
//var property = type.GetProperty(getter.Key);
//var attribute = property.GetCustomAttribute<SerializeNullAttribute>();
//if (attribute == null)
//{
// continue;
//}
} }
jsonObject.Add(MapClrMemberNameToJsonFieldName(getter.Key), value); jsonObject.Add(MapClrMemberNameToJsonFieldName(getter.Key), value);

View File

@@ -2,6 +2,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using Octokit.Internal;
namespace Octokit namespace Octokit
{ {
@@ -29,6 +30,7 @@ namespace Octokit
/// <remarks> /// <remarks>
/// Only users with push access can set the assignee for new issues. The assignee is silently dropped otherwise. /// Only users with push access can set the assignee for new issues. The assignee is silently dropped otherwise.
/// </remarks> /// </remarks>
[SerializeNull]
public string Assignee { get; set; } public string Assignee { get; set; }
/// <summary> /// <summary>
@@ -38,6 +40,7 @@ namespace Octokit
/// Only users with push access can set the milestone for new issues. The milestone is silently dropped /// Only users with push access can set the milestone for new issues. The milestone is silently dropped
/// otherwise /// otherwise
/// </remarks> /// </remarks>
[SerializeNull]
public int? Milestone { get; set; } public int? Milestone { get; set; }
/// <summary> /// <summary>