Jaex Jaex - 2 months ago 39
C# Question

Is there a way to ignore get-only properties in Json.NET without using JsonIgnore attributes?

Is there a way to ignore get-only properties using the Json.NET serializer but without using

JsonIgnore
attributes?

For example, I have a class with these get properties:

public Keys Hotkey { get; set; }

public Keys KeyCode
{
get
{
return Hotkey & Keys.KeyCode;
}
}

public Keys ModifiersKeys
{
get
{
return Hotkey & Keys.Modifiers;
}
}

public bool Control
{
get
{
return (Hotkey & Keys.Control) == Keys.Control;
}
}

public bool Shift
{
get
{
return (Hotkey & Keys.Shift) == Keys.Shift;
}
}

public bool Alt
{
get
{
return (Hotkey & Keys.Alt) == Keys.Alt;
}
}

public Modifiers ModifiersEnum
{
get
{
Modifiers modifiers = Modifiers.None;

if (Alt) modifiers |= Modifiers.Alt;
if (Control) modifiers |= Modifiers.Control;
if (Shift) modifiers |= Modifiers.Shift;

return modifiers;
}
}

public bool IsOnlyModifiers
{
get
{
return KeyCode == Keys.ControlKey || KeyCode == Keys.ShiftKey || KeyCode == Keys.Menu;
}
}

public bool IsValidKey
{
get
{
return KeyCode != Keys.None && !IsOnlyModifiers;
}
}


Do I need to add
[JsonIgnore]
to all of them (I also have many other classes), or there is better way to ignore all get-only properties?

Answer

You can do this by implementing a custom IContractResolver and using that during serialization. If you subclass the DefaultContractResolver, this becomes very easy to do:

class WritablePropertiesOnlyResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
        return props.Where(p => p.Writable).ToList();
    }
}

Here is a test program demonstrating how to use it:

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

class Program
{
    static void Main(string[] args)
    {
        Widget w = new Widget { Id = 2, Name = "Joe Schmoe" };

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new WritablePropertiesOnlyResolver()
        };

        string json = JsonConvert.SerializeObject(w, settings);

        Console.WriteLine(json);
    }
}

class Widget
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string LowerCaseName
    {
        get { return (Name != null ? Name.ToLower() : null); }
    }
}

Here is the output of the above. Notice that the read-only property LowerCaseName is not included in the output.

{"Id":2,"Name":"Joe Schmoe"}
Comments