CanConvert
当您标记某物时不会被调用[JsonConverter]
。当您使用该属性时,Json.Net 假定您已经提供了正确的转换器,因此它不会打扰CanConvert
查看。如果删除该属性,那么它将通过将转换器实例传递给设置来调用。您所看到的是 Json.Net 测试您的转换器的所有其他属性类型。
EDIT
我快速整理了一个fiddle https://dotnetfiddle.net/kYblzk来展示我的意思(为了完整性,下面也复制了代码)。
在不改变程序的情况下,CanConvert()
被呼叫FooConverter
适用于所有类型except Foo
,但它仍然转换Foo
正确。
如果你注释掉[JsonConverter]
属性上的Wrapper.Foo
属性,你可以看到CanConvert()
现在将被要求输入类型Foo
凭借FooConverter
被纳入其中JsonSerializerSettings
.
如果您注释掉中的行Main
哪里的FooConverter
添加到设置中,然后CanConvert
从未被任何类型调用过,但是Foo
仍然可以正确转换,因为[JsonConverter]
属性应用于Foo
财产在Wrapper
class.
因此,这里的要点是,有两种机制可以指示是否应使用转换器,但您不需要同时使用这两种机制。您可以应用一个属性,这将告诉 Json.Net 应该将特定的转换器用于特定的属性(或类),并且不需要首先询问转换器。或者,您可以将转换器添加到设置中,在这种情况下,Json.Net 必须询问每个转换器是否可以处理每种类型。前者效率更高一些,而后者在您不拥有要转换的类的源代码的情况下很有用。希望这是有道理的。
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
public class Program
{
public static void Main()
{
JsonSerializerSettings settings = new JsonSerializerSettings();
// Comment out the following line and CanConvert() never gets called on
// FooConverter for any type yet the FooConverter is still working due
// to the JsonConverter attribute applied to Wrapper.Foo
settings.Converters.Add(new FooConverter());
settings.Converters.Add(new BarConverter());
settings.Formatting = Formatting.Indented;
Wrapper w = new Wrapper
{
Foo = new Foo
{
A = "bada",
B = "boom",
},
Bar = new Bar
{
C = "bada",
D = "bing"
}
};
string json = JsonConvert.SerializeObject(w, settings);
Console.WriteLine(json);
}
class Wrapper
{
// Comment out this attribute and CanConvert will be called on FooConverter
// for type Foo due to the fact that the FooConverter has been added to the
// JsonSerializerSettings
[JsonConverter(typeof(FooConverter))]
public Foo Foo { get; set; }
public Bar Bar { get; set; }
}
class Foo
{
public string A { get; set; }
public string B { get; set; }
}
class Bar
{
public string C { get; set; }
public string D { get; set; }
}
class FooConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool result = typeof(Foo).IsAssignableFrom(objectType);
Console.WriteLine("FooConverter CanConvert() called for type " +
objectType.Name + " (result = " + result + ")");
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var foo = (Foo) value;
JObject jo = new JObject();
jo.Add("AplusB", new JValue(foo.A + " " + foo.B));
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
class BarConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool result = typeof(Bar).IsAssignableFrom(objectType);
Console.WriteLine("BarConverter CanConvert() called for type " +
objectType.Name + " (result = " + result + ")");
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var bar = (Bar) value;
JObject jo = new JObject();
jo.Add("CplusD", new JValue(bar.C + " " + bar.D));
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}