Json.NET как переопределить сериализацию для типа, который определяет пользовательский JsonConverter через атрибут?

Я пытаюсь десериализовать класс, используя Json.NET и пользовательский объект JsonConverter. Класс в настоящее время определяет конвертер для сериализации по умолчанию с использованием JsonConverterAttribute. Мне нужно сделать обычную десериализацию, передав в пользовательский конвертер. Однако десериализация все еще, по-видимому, использует преобразователь по умолчанию. Как я могу заставить Json.NET предпочесть мой пользовательский конвертер?

Вот несколько примеров кода, который демонстрирует проблему. Я использую NewtonSoft.Json 4.5.11:

void Main()
{
    JsonConvert.DeserializeObject<Foo>("{}"); // throws "in the default converter"
    var settings = new JsonSerializerSettings { Converters = new[] { new CustomConverter() } };
    JsonConvert.DeserializeObject<Foo>("{}", settings); // still throws "in the default converter" :-/
}

[JsonConverter(typeof(DefaultConverter))]
public class Foo {
}

public class DefaultConverter : JsonConverter {
    public override bool CanConvert(Type objectType)
    {
        return typeof(Foo).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new Exception("in the default converter!");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new Exception("in the default converter!");
    }
}

public class CustomConverter : JsonConverter {
    public override bool CanConvert(Type objectType)
    {
        return typeof(Foo).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new Exception("in the custom converter!");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new Exception("in the custom converter!");
    }
}

Ответы

Ответ 1

Вам нужно использовать пользовательский разрешитель контрактов. По умолчанию для решения по умолчанию используются преобразователи из настроек, только если для типа не указан конвертер.

class CustomContractResolver : DefaultContractResolver
{
    protected override JsonConverter ResolveContractConverter (Type objectType)
    {
        if (typeof(Foo).IsAssignableFrom(objectType))
            return null; // pretend converter is not specified
        return base.ResolveContractConverter(objectType);
    }
}

Использование:

JsonConvert.DeserializeObject<Foo>("{}", new JsonSerializerSettings {
    ContractResolver = new CustomContractResolver(),
    Converters = new[] { new CustomConverter() },
});