在Json.Net中全局注册自定义JsonConverter

Meh*_*ran 41 c# json.net

使用Json.Net,我的对象中的属性需要特别小心才能序列化/反序列化它们.作为后代JsonConverter,我成功地完成了这一任务.这是执行此操作的常用方法:

public class SomeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        ...
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        ...
    }

    public override bool CanConvert(Type objectType)
    {
        ...
    }
}

class SomeClass
{
    [JsonProperty, JsonConverter(typeof(SomeConverter))]
    public SomeType SomeProperty;
}

//Later on, in code somewhere
SomeClass SomeObject = new SomeClass();
string json = JsonConvert.SerializeObject(SomeObject, new SomeConverter());
Run Code Online (Sandbox Code Playgroud)

我的代码问题是我需要在每个序列化/反序列化中引入我的自定义转换器.在我的项目中,有很多情况我不能这样做.例如,我正在使用其他利用Json.Net的外部项目,他们将在我的SomeClass实例上工作.但由于我不想或无法改变他们的代码,我无法介绍我的转换器.

有没有什么方法可以static在Json.Net中使用某个成员注册我的转换器,所以无论序列化/反序列化发生在哪里,我的转换器总是存在?

Bri*_*ers 66

是的,这可以使用Json.Net 5.0.5或更高版本.见JsonConvert.DefaultSettings.

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new SomeConverter() }
};

// Later on...
string json = JsonConvert.SerializeObject(someObject);  // this will use SomeConverter
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Web API,则可以像这样全局设置转换器:

var config = GlobalConfiguration.Configuration;
var jsonSettings = config.Formatters.JsonFormatter.SerializerSettings;
jsonSettings.Converters.Add(new SomeConverter());
Run Code Online (Sandbox Code Playgroud)


Yis*_*zer 14

另一种方法(优先于上述@Brian提及的方法获胜)是实现自定义合同解析器

JsonFormatter.SerializerSettings.ContractResolver = new CustomContractResolver();
Run Code Online (Sandbox Code Playgroud)

而且实施相当简单

public class CustomContractResolver : DefaultContractResolver
{
    private static readonly JsonConverter _converter = new MyCustomConverter();
    private static Type _type = typeof (MyCustomType);

    protected override JsonConverter ResolveContractConverter(Type objectType)
    {
        if (objectType == null || !_type.IsAssignableFrom(objectType)) // alternatively _type == objectType
        {
            return base.ResolveContractConverter(objectType);
        }

        return _converter;
    }
}
Run Code Online (Sandbox Code Playgroud)

这两种方法都是有效的,这只是一个更大的锤子