gpt4 book ai didi

c# - JsonConverter CanConvert 不接收类型

转载 作者:太空狗 更新时间:2023-10-29 17:40:13 24 4
gpt4 key购买 nike

我有一个自定义的 JsonConverter,它似乎没有被正确调用。我已经创建了转换器,将其添加到 JsonSerializerSettings.Converters 集合中,并在我使用 [JsonConverter(typeof(SearchGeoConverter))] 序列化的实体上标记了属性,但是即使有这些,转换器 CanConvert 方法也永远看不到我要转换的类型。我只见过 stringintJObject

我的转换器看起来像这样:

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();
}
}

我错过了什么?

最佳答案

当您使用 [JsonConverter] 标记某些内容时,

CanConvert 不会被调用。当您使用该属性时,Json.Net 假定您提供了正确的转换器,因此它不会理会 CanConvert 检查。如果您删除该属性,那么它将通过您将转换器实例传递给设置而被调用。您看到的是 Json.Net 测试所有其他属性类型的转换器。

编辑

我快速整理了一份 fiddle显示我的意思(为了完整性还在下面复制了代码)。

在不更改程序的情况下,CanConvert() 会在 FooConverter 上针对所有类型 except Foo 调用,但它仍能正确转换 Foo

如果您在 Wrapper.Foo 属性上注释掉 [JsonConverter] 属性,您可以看到 CanConvert() 现在将获得由于 JsonSerializerSettings 中包含 FooConverter,因此调用类型 Foo

如果您改为注释掉 Main 中将 FooConverter 添加到设置中的行,则永远不会为任何类型调用 CanConvert ,但由于 [JsonConverter] 属性应用于 Wrapper 中的 Foo 属性,因此 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();
}
}
}

关于c# - JsonConverter CanConvert 不接收类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26016119/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com