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

Viewed 4058

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?

4 Answers

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()
    });

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;
    }

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.

Related