0

I am trying to implement field selection within Web Api but cannot get this to work for named nested properties. I am doing this with the code below.

Here is the aggregate that I am using in my example:

public class Release
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Artist Artist { get; set; }
    public string Genre { get; set; }
}

public class Artist
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Label Label { get; set; }
}

public class Label
{
    public int Id { get; set; }
    public string Name { get; set; }
    public LabelOwner Owner { get; set; }
}

public class LabelOwner
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And the Json.Net Resolver I have written:

public class NamedFieldSerializer<T> : DefaultContractResolver
{
    private readonly string _typeName;

    private readonly string[] _fields;

    public NamedFieldSerializer(string fields)
    {
        _typeName = typeof(T).Name;
        _fields = fields.Split(',').Select(x =>
        {
            var field = x.Trim();
            if (!field.Contains("."))
            {
                field = $"{_typeName}.{field}";
            }

            return field.ToLower();

        }).ToArray();
    }

    private bool NoFieldsSpecified()
    {
        return !_fields.Any();
    }

    private bool IsNestedType(MemberInfo member)
    {
        var prop = member as PropertyInfo;
        var isSystemType = prop.PropertyType.FullName.StartsWith("System");
        return !isSystemType && _fields.Any(x => x.Contains($"{member.Name}.".ToLower()));
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        property.ShouldSerialize = _ =>
        {
            if (NoFieldsSpecified()) return true;

            if (IsNestedType(member)) return true;

            var prop = member as PropertyInfo;

            var fullMemberName = $"{prop.ReflectedType.Name}.{member.Name}".ToLower();

            var split = _fields.Select(x => x.Split(new [] { fullMemberName }, StringSplitOptions.RemoveEmptyEntries));

            return split.Any(x => x.Length == 0 || (x.Length == 1 && x.First().EndsWith("."))); 
        };

        return property;
    }
}

Where fields is "title,genre,artist.name,artist.label.name,artist.label.owner.name"

Now this does work if the property name used in the fields is the same as the type. I cannot use a different name like for "artist.label.owner.name", it does however work for "artist.label.labelowner.name"

Anyone got any ideas?

jonytek
  • 111
  • 2
  • 7
  • Can you post your json? – aloisdg Mar 06 '17 at 16:39
  • Your question is unclear. Could you give a sample of the JSON you are trying to create, and what you are getting currently? Your question does sound similar to [How to perform partial object serialization providing “paths” using Newtonsoft JSON.NET](http://stackoverflow.com/q/30304128/3744182) or [Json.NET serialize by depth and attribute](http://stackoverflow.com/q/36159424/3744182) so perhaps it's a duplicate. – dbc Mar 06 '17 at 16:41

0 Answers0