我有一个定制的JsonConverter,它似乎没有被正确地调用。我已经创建了转换器,将它添加到JsonSerializerSettings.Converters集合中,并在我使用[JsonConverter(typeof(SearchGeoConverter))]序列化的实体上标记了属性,但是即使有了这些转换器,CanConvert方法也看不到我试图转换的类型。我只看过,string,int和JObject。
我的转换器看起来如下:
public class SearchGeoConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DbGeography).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var point = (DbGeography) value;
var rawJson = string.Format("{{ \"type\": \"Point\", \"coordinates\": [{0}, {1}] }}", point.Latitude, point.Longitude);
writer.WriteRaw(rawJson);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}我遗漏了什么?
发布于 2014-09-24 13:38:53
当您用CanConvert标记某物时,不会调用[JsonConverter]。当您使用该属性时,Json.Net假设您已经提供了正确的转换器,因此它不需要使用CanConvert检查。如果删除该属性,则将通过将转换器实例传递给设置来调用该属性。您看到的是Json.Net测试转换器的所有其他属性类型。
编辑
我组装了一个快速的fiddle来展示我的意思(为了完整起见,代码也在下面被复制)。
在不改变程序的情况下,CanConvert()会在FooConverter上为除Foo以外的所有类型调用,但它仍然正确地转换Foo。
如果您注释掉Wrapper.Foo属性上的Wrapper.Foo属性,您可以看到CanConvert()现在将被调用类型Foo,这是因为FooConverter包含在JsonSerializerSettings中。
如果您在Main中注释掉将FooConverter添加到设置中的行,则不会为任何类型调用CanConvert,但是由于应用于Wrapper类中的Foo属性的[JsonConverter]属性,Foo仍然被正确转换。
因此,这里的优点是有两种机制来指示是否应该使用转换器,而您不需要这两种机制。您可以应用一个属性,这将告诉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();
}
}
}https://stackoverflow.com/questions/26016119
复制相似问题