C# 如何覆盖默认JsonConverter(在属性中指定)

C# 如何覆盖默认JsonConverter(在属性中指定),c#,json,.net-core,json.net,C#,Json,.net Core,Json.net,我希望下面的Author类型具有默认的JsonConverter,并且能够在运行时覆盖它 [JsonConverter(typeof(BaseJsonConverter))] 公共类作者 { //应用程序中作者实体的ID。 公共int ID{set;get;} //源中作者实体的ID。 公共字符串SourceID{set;set;} } 我使用以下代码覆盖默认转换器(即,BaseJsonConverter) 公共类可选转换器:BaseJsonConverter {//为了清晰起见,已删除序列化

我希望下面的
Author
类型具有默认的
JsonConverter
,并且能够在运行时覆盖它

[JsonConverter(typeof(BaseJsonConverter))]
公共类作者
{
//应用程序中作者实体的ID。
公共int ID{set;get;}
//源中作者实体的ID。
公共字符串SourceID{set;set;}
}
我使用以下代码覆盖默认转换器(即,
BaseJsonConverter

公共类可选转换器:BaseJsonConverter
{//为了清晰起见,已删除序列化程序实现。}
//使用AlternativeConverter反序列化:
var author=JsonConvert.DeserializeObject


用例 该应用程序将从不同来源获得的不同JSON对象转换为通用C#类型。通常,数据来自我们定义默认转换器的源(即,
BaseJsonConverter
),对于来自其他源的数据,我们为每个源定义不同的转换器


背景 我知道一些方法,例如,事实上,我正在部分使用类似的方法。参考那篇文章,我需要根据输入的来源使用不同的
\u propertyMappings
,因为在我的应用程序中属性到属性的映射不是一对一的。例如,我有以下JSON对象:

{
   "id":123
}

// and

{
   "id":"456"
}
其中第一个JSON对象应反序列化为:

author.ID=123
author.SourceID=null
第二个JSON对象应反序列化为:

author.ID=0
author.SourceID=“456”

我认为您应该尝试对不同的数据源、不同的集合使用不同的
JsonSerializerSettings
实例。并从类中删除
JsonConverter
属性。

您可以使用自定义来以编程方式重写
[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;
    }
}
// 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);
演示小提琴:



当然,如果您真正使用这些转换器所做的只是将属性重新映射到不同的名称,那么您可以首先使用
ContractResolver
来实现这一点,然后完全去掉这些转换器。有关该方法的更多信息,请参阅。

从我看到的情况来看,您的json键是相同的。这些值只是不同而已。那么,为什么不试着将json字符串解析为一个
JToken
,作为所需的C#对象呢?除非我不太明白你的问题,否则你的生活似乎很艰难。仅仅拥有一个json对象不足以决定哪个json属性应该映射到哪个属性。因此,需要在输入源的上下文中进行反序列化,即为来自不同源的JSON提供不同的转换器。实际上是这样的。JToken是动态的。您已经有一个名为
Author
的对象。如果您知道传入的json类型为
Author
,请在每个变量的顶部添加
[JsonProperty(“blabla”)]
,并将其解析为
JToken
,剩下的部分由C完成。再说一次,如果我没抓住重点,一定要让我知道。谢谢你的建议,但是是的,我想你没抓住重点。如果我遵循您的建议(我现在正在尝试避免这样做),将有多个带有
[JsonProperty(“blabal”)]
的属性。例如,
ID
SourceID
都将有
[JsonProperty(“ID”)]
,请看Json示例。啊,现在我明白了,你想做什么。根据类型,您试图将传入的json“id”附加到Author中的一个属性。如果它是int,则转换为int。Get itI无法删除
JsonConvert
属性,因为它对于默认类型的(反)序列化是必不可少的。此外,我尝试使用类似于
转换器的东西,但是,通过
JsonConverter
属性设置的默认转换器会覆盖我传递的任何序列化程序。