AngryHacker
AngryHacker

Reputation: 61606

Any way to get JsonConvert.SerializeObject to ignore the JsonConverter attribute on a property?

I have a class that I cannot change:

public enum MyEnum {
    Item1 = 0,
    Item2 = 1
}
public class foo {
    [JsonConverter(typeof(StringEnumConverter))]
    public MyEnum EnumTypes {get; set; }
}

Somewhere down the line JsonConvert.SerializeObject serializes the object and because of the JsonConverter attribute, it spits out name of the enum value for the foo.EnumTypes rather than the number.

Is there anyway to get JsonConvert.SerializeObject to ignore the attribute on the EnumTypes property?

Upvotes: 13

Views: 8607

Answers (5)

harwex213
harwex213

Reputation: 11

You could use JsonIgnore attribute

public class Object
{
    public string Key { get; set; }

    [JsonIgnore]
    public string Value { get; set; }
}

Upvotes: 1

tmaj
tmaj

Reputation: 34967

I'm a simple man and I would create separate DTO, copy the data into that object and serialise this DTO and not the original object.

Upvotes: 1

Alex K.
Alex K.

Reputation: 814

The previous comment looked really promising, but for some reason it didn't work for me. I modified accepted answer to fit my needs. Here is the code if anyone ever needs it

public class IgnoreConvertersContractResolver : DefaultContractResolver
{
    private readonly Type[] _typesToIgnore;

    public IgnoreConvertersContractResolver(params Type[] typesToIgnore)
    {
        _typesToIgnore = typesToIgnore;
    }

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

        foreach (var attribute in attributes)
        {
            if (attribute is JsonConverterAttribute converterAttribute 
                && _typesToIgnore.Contains(converterAttribute.ConverterType))
            {
                property.Converter = null;
                break;
            }
        }

        return property;
    }

Upvotes: 2

sarh
sarh

Reputation: 6627

Kyle's answer is a great starting point. It works fine in this concrete simple example from question. But for me it didn't work recursively for the nested properties, at least with newtonsoft.json v12.0.3. Looking at what else can be overwritten in DefaultContractResolver I've found

public virtual JsonContract ResolveContract(Type type);

and it worked fine for nested properties:

    internal sealed class NumericEnumContractResolver : DefaultContractResolver
    {
        private Type _stringEnumConverterType = typeof(StringEnumConverter);

        protected override JsonConverter ResolveContractConverter(Type objectType)
        {
            var converter = base.ResolveContractConverter(objectType);

            if ((converter != null) &&
                (converter.GetType() == _stringEnumConverterType))
            {
                converter = null;
            }

            return converter;
        }
    }

and sample usage:

JsonConvert.SerializeObject(
    myObject,
    new SerializerSettings
    {
        ContractResolver = new NumericEnumContractResolver()
    });

Upvotes: 2

Kyle
Kyle

Reputation: 6684

This is possible, but the process is a tad involved.

The basic idea is to create a custom ContractResolver and override its CreateProperty method. Something like so:

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

        if( member.DeclaringType == typeof( foo ) && property.PropertyType == typeof( MyEnum ) )
        {
            property.Converter = null;
        }

        return property;
    }
}

You'll also need to actually instantiate this class and pass it into your serializer/deserializer. What that looks like depends on exactly how you're doing the serialization, so I can't guarantee a relevant example of how to use it.

If you're just using the static SerializeObject method:

JsonConvert.SerializeObject( valueToSerialize, new SerializerSettings { ContractResolver = new MyContractResolver() } );

Upvotes: 12

Related Questions