6

Is there an attribute to tell json.net to ignore all properties of a class but include all fields (regardless of access modifiers) ?

If not is there a way to create one ?

Basically I want one attribute decorating the class that will have the equivalent effect to putting [JsonIgnore] infront of each property.

3 Answers 3

9

You can add [JsonObject(MemberSerialization.OptIn)] attribute to your class, then everything will be ignored unless you explicitly Opt-In by using a [JsonProperty] attribute on the members.

[JsonObject(MemberSerialization.OptIn)]
public class Address
{
    [JsonProperty]
    private string _field1 = "bob";

    public string Line1 { get; set; }

    public string Line2 { get; set; }

    public string Line3 { get; set; }
}

For example

using System;
using AutoFixture;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        var fixture = new Fixture();
        var address = fixture.Create<Address>(); // Create an address filled with junk

        var json = JsonConvert.SerializeObject(address);

        Console.WriteLine(json);
    }
}

Will output:

{"_field1":"bob"}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks I am specifically looking for a single attribute I can apply to the class and forget about it if I later add/remove fields etc
But.. The code in the answer from Kevin will do that, @kofifus. It's tagged as opt-in. It's exactly the same as excluding everything but the things you say otherwise.
imagine I have ten fields, I'll need ten [JsonProperty] with your solution
3
+50

If you mark your class with [JsonObject(MemberSerialization.Fields)], that will get you most of the way there. This attribute tells Json.Net that you want it to serialize all fields in a class, regardless of access modifiers, but not properties.

However, if you have any auto properties in your class (i.e. those declared with { get; set; }) then this attribute will cause the compiler-generated backing fields to be serialized as well, which you may not want. To suppress those, you will need to use a custom IContractResolver. You can create one by inheriting from the DefaultContractResolver and overriding the CreateProperty method. In that method, check whether the class has the [JsonObject(MemberSerialization.Fields)] attribute applied, and if so, check whether the member is a compiler-generated field. If it is, then set it to be ignored.

class CustomResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        JsonObjectAttribute attr = prop.DeclaringType.GetCustomAttribute<JsonObjectAttribute>();
        if (attr != null && attr.MemberSerialization == MemberSerialization.Fields && 
            member.GetCustomAttribute<CompilerGeneratedAttribute>() != null)
        {
            prop.Ignored = true;
        }
        return prop;
    }
}

To use the resolver, you need to pass it to the SerializeObject method via the JsonSerializerSettings:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CustomResolver(),
    Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(yourObject, settings);

Here is a proof of concept: https://dotnetfiddle.net/aNXWbn

1 Comment

[JsonObject(MemberSerialization.Fields)] was what I was looking for
0

You could create a custom IContractResolver and decide to serialize depending on a custom attribute you created:

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

        //Todo: Check your custom attribute. You have MemberInfo here to navigate to your class and GetCustomAttributes<>
        //e.g: property.ShouldSerialize = member.DeclaringType.GetCustomAttribute<JsonIgnoreAllProperties>() == null;
        property.ShouldSerialize = false; 
        return property;
    }
}

Then you need to register it as default, which depends on your environment. Or you are using it directly, then you even do not need an attribute:

string json =
    JsonConvert.SerializeObject(
        product,
        Formatting.Indented,
        new JsonSerializerSettings
        {
            ContractResolver = new IgnorePropertyResolver()
        }
    );

An attribute is created for example by:

public class JsonIgnoreAllPropertiesAttribute : Attribute
{
}

And Used:

[JsonIgnoreAllProperties]
public class ClassToSerialize
{
     public int Ignored { get;set; }
     public int Serialized;
}

3 Comments

it's not a 'custom attribute' I want to decorate my class so that all fields are considered and all properties are ignored, just as if I had [JsonIgnore] infront of each property
Yeah, that seems not to be supported. So if you want to: You need to create a custom one [JsonIgnoreAllProperties] @kofifus
any tips on how to do that ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.