首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JsonConverter CanConvert不接收类型

JsonConverter CanConvert不接收类型
EN

Stack Overflow用户
提问于 2014-09-24 11:46:44
回答 1查看 9.1K关注 0票数 15

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

我的转换器看起来如下:

代码语言:javascript
复制
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();
    }
}

我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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必须询问每个转换器是否能够处理每种类型。前者的效率要高一些,而后者在您不拥有要转换的类的源代码的情况下很有用。希望这是有意义的。

代码语言:javascript
复制
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();
        }
    }
}
票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26016119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档