Making a property deserialize but not serialize with json.net

Viewed 106258

We have some configuration files which were generated by serializing C# objects with Json.net.

We'd like to migrate one property of the serialised class away from being a simple enum property into a class property.

One easy way to do this, would be to leave the old enum property on the class, and arrange for Json.net to read this property when we load the config, but not to save it again when we next serialize the object. We'll deal with generating the new class from the old enum separately.

Is there any simple way to mark (e.g. with attributes) a property of a C# object, so that Json.net will ignore it ONLY when serializing, but attend to it when deserializing?

13 Answers

Depending on where in the application this takes place and if it's just one property, one manual way you can do this is by setting the property value to null and then on the model you can specify that the property be ignored if the value is null:

[JsonProperty(NullValueHandling = NullValue.Ignore)]
public string MyProperty { get; set; }

If you are working on an ASP.NET Core web app, you can globally set this for all properties in all models by setting this in your Startup.cs file:

public void ConfigureServices(IServiceCollection services) {
    // other configuration here
    services.AddMvc()
        .AddJsonOptions(options => options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore);
}

To build upon Tho Ho's answer, this can also be used for fields.

[JsonProperty(nameof(IgnoreOnSerializing))]
public string IgnoreOnSerializingSetter { set { IgnoreOnSerializing = value; } }

[JsonIgnore]
public string IgnoreOnSerializing;

If you use JsonConvert,IgnoreDataMemberAttribute is ok.My standard library not refrence Newton.Json,and I use [IgnoreDataMember] to control object serialize.

From Newton.net help document.

Is there any simple way to mark (e.g. with attributes) a property of a C# object, so that Json.net will ignore it ONLY when serializing, but attend to it when deserializing?

The easiest way I've found as of this writing is to include this logic in your IContractResolver.

Sample code from above link copied here for posterity:

public class Employee
{
    public string Name { get; set; }
    public Employee Manager { get; set; }

    public bool ShouldSerializeManager()
    {
        // don't serialize the Manager property if an employee is their own manager
        return (Manager != this);
    }
}

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();

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

        if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager")
        {
            property.ShouldSerialize =
                instance =>
                {
                    Employee e = (Employee)instance;
                    return e.Manager != e;
                };
        }

        return property;
    }
}

All of the answers are good but this approach seemed like the cleanest way. I actually implemented this by looking for an attribute on the property for SkipSerialize and SkipDeserialize so you can just mark up any class you control. Great question!

Jraco11's answer is very neat. In case, if you want to use the same IContractResolver both for serialization and deserialization, then you can use the following:

public class JsonPropertiesResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (member.IsDefined(typeof(JsonIgnoreSerializationAttribute)))
        {
            property.ShouldSerialize = instance => false;
        }

        return property;
    }
}

thats will do the trick, create a property with set only

example 1: https://dotnetfiddle.net/IxMXcG

[JsonProperty("disabled-protections")]
public JArray DisabledProtections { set => IsPartialResult = (value != null && value.HasValues); }

public bool IsPartialResult { get; private set; }

example 2:

private JArray _disabledProtections;

[JsonProperty("disabled-protections")]
public JArray DisabledProtections { set => _disabledProtections = value; }

public bool IsPartialResult => _disabledProtections != null && _disabledProtections.HasValues;

Use [JsonIgnore] attribute in the public property of the model class.

Related