Как переопределить JsonConverter по умолчанию (указанный в атрибуте) - PullRequest
3 голосов
/ 11 марта 2020

Мне бы хотелось, чтобы следующий тип Author имел значение по умолчанию JsonConverter и мог бы переопределить его во время выполнения.

[JsonConverter(typeof(BaseJsonConverter))]
public class Author
{
    // The ID of an author entity in the application.
    public int ID { set; get; }

    // The ID of an Author entity in its source.
    public string SourceID { set; set; }
}

Я использовал следующий код для переопределения конвертера по умолчанию (т. Е. BaseJsonConverter).

public class AlternativeConverter : BaseJsonConverter
{ // the serializer implementation is removed for clarity. }

// Deserialize using AlternativeConverter:
var author = JsonConvert.DeserializeObject<Author>(jsonString, new AlternativeConverter());

Вопрос

Использование вышеуказанного вызова AlternativeConverter сначала строится; однако затем экземпляр BaseJsonConverter инициализируется и используется для десериализации. Таким образом, AlternativeConverter никогда не используется.

Пример выполнения: https://dotnetfiddle.net/l0bgYO


Вариант использования

Приложение должно конвертировать различные JSON объекты, полученные из разных источников, в общий тип C#. Обычно данные поступают из источника, для которого мы определяем конвертер по умолчанию (т. Е. BaseJsonConverter), а для данных, поступающих из других источников, мы определяем разные конвертеры для каждого.


Фон

Мне известны такие методы, как этот , и я действительно использую подобный метод частично. Что касается ссылки на эту статью, мне нужно иметь разные _propertyMappings в зависимости от источника ввода, потому что в моем приложении атрибут сопоставления свойств не один-к-одному. Например, у меня есть следующие JSON объекты:

{
   "id":123
}

// and

{
   "id":"456"
}

, где первый JSON объект должен быть десериализован в:

author.ID = 123
author.SourceID = null

, а второй JSON объект должен быть десериализованным как:

author.ID = 0
author.SourceID = "456"

Ответы [ 2 ]

1 голос
/ 11 марта 2020

Вы можете использовать пользовательский ContractResolver для программного переопределения атрибута [JsonConverter]. Чтобы решить вашу проблему, вы можете создать собственный распознаватель, такой как:

public class CustomResolver : DefaultContractResolver
{
    private Dictionary<Type, JsonConverter> Converters { get; set; }

    public CustomResolver(Dictionary<Type, JsonConverter> converters)
    {
        Converters = converters;
    }

    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        JsonObjectContract contract = base.CreateObjectContract(objectType);
        if (Converters.TryGetValue(objectType, out JsonConverter converter))
        {
            contract.Converter = converter;
        }
        return contract;
    }
}

Затем, когда вы захотите использовать AlternativeConverter вместо BaseJsonConverter, вы можете использовать настраиваемый распознаватель, например так:

// map the `Author` type to the `AlternativeConverter`
var converters = new Dictionary<Type, JsonConverter>()
{
    { typeof(Author), new AlternativeConverter() }
};

// Create a resolver with the converter mapping and add it to the serializer settings
var settings = new JsonSerializerSettings
{
    ContractResolver = new CustomResolver(converters)
};

// Use the settings when deserializing
var author = JsonConvert.DeserializeObject<Author>(jsonString, settings);

Demo Fiddle: https://dotnetfiddle.net/cu0igV


Конечно, если все, что вы действительно делаете с этими конвертерами, это переназначение свойств на разные имена, Вы могли бы просто использовать ContractResolver для этого в первую очередь и вообще избавиться от конвертеров. См. Json. NET десериализацию или сериализацию json строк и сопоставление свойств с различными именами свойств, определенными во время выполнения для получения дополнительной информации об этом подходе.

0 голосов
/ 11 марта 2020

Я думаю, вы должны попытаться использовать разные JsonSerializerSettings экземпляры для разных источников данных с разными конвертерами коллекций. И удалите JsonConverter атрибуты из ваших классов.

...