JsonConverter CanConvert 不接收类型

2024-01-06

我有一个习惯JsonConverter,这似乎没有被正确调用。我已经创建了转换器,并将其添加到JsonSerializerSettings.Converters集合并标记了我正在序列化的实体上的属性[JsonConverter(typeof(SearchGeoConverter))],但即使有了这些转换器CanConvert方法永远不会看到我试图转换的类型。我只见过,string, int and 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();
    }
}

我缺少什么?


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();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JsonConverter CanConvert 不接收类型 的相关文章

  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • 从父类调用子类方法

    a doStuff 方法是否可以在不编辑 A 类的情况下打印 B did stuff 如果是这样 我该怎么做 class Program static void Main string args A a new A B b new B a
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • 如何返回 json 结果并将 unicode 字符转义为 \u1234

    我正在实现一个返回 json 结果的方法 例如 public JsonResult MethodName Guid key var result ApiHelper GetData key Data is stored in db as v
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐