1

我的问题是我需要将 JSON 反序列化为包含接口类型对象的类型,因此需要指示 Json.NET 如何转换该接口类型,但不能Newtonsoft.Json.Deserializer直接控制。反序列化由框架代码间接处理,即HttpContent.ReadAsAsync<T>

如何指定从接口类型到具体类型的转换,而不能JsonSerializer.Converters直接添加转换器?如果我[JsonConverter]在接口定义上使用该属性,则转换器也会被调用以实现接口(即,我要转换为的具体类型)。

下面的代码显示了一个 C# 控制台程序,它尝试将相同的 JSON 反序列化为首先是Parent2类,然后是Parent1类,指示 Json.NET 将IChild1接口Child1类型通过JsonConverterAttribute. Parent2自从我ChildConverter直接添加 to后,反序列化就可以工作serializer.Converters,而反序列化 toParent1会导致堆栈溢出异常,因为即使是针对该类型ChildConverter.Deserialize也被调用。Child1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;

namespace TestConsole
{
    [JsonConverter(typeof(ChildConverter))]
    interface IChild1
    {
        string Name { get; set; }
    }

    class Child1 : IChild1
    {
        public string Name { get; set; }
    }

    class Parent1
    {
        public IEnumerable<IChild1> Children { get; set; }
    }

    interface IChild2
    {
        string Name { get; set; }
    }

    class Child2 : IChild2
    {
        public string Name { get; set; }
    }

    class Parent2
    {
        public IEnumerable<IChild2> Children { get; set; }
    }

    class ChildConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(IChild1) || objectType == typeof(IChild2);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (objectType == typeof(IChild1))
                return serializer.Deserialize<Child1>(reader);
            return serializer.Deserialize<Child2>(reader);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var json = "{'Children': [{'Name': 'Child1'}, {'Name': 'Child2'}]}";

            var serializer = new JsonSerializer();

            serializer.Converters.Add(new ChildConverter());
            var obj = serializer.Deserialize(new StringReader(json), typeof(Parent2));

            serializer = new JsonSerializer();
            obj = serializer.Deserialize(new StringReader(json), typeof(Parent1));
        }
    }
}
4

1 回答 1

1

我找到了解决我的特定问题的方法,即调用HttpContent.ReadAsAsync<T>并让其反序列化 JSON 响应。虽然我的解决方案不能解决在不访问序列化程序的情况下配置 Json.NET 类型转换的一般问题,但它确实解决了我的特定问题。我发现HttpContent.ReadAsync<T>接受一个IEnumerable<MediaTypeFormatter>, 用于反序列化响应。在这里可以传递一个JsonMediaTypeFormatter,它已根据您JsonConverter的选择进行配置(在我的示例中,ChildConverter)。

var formatter = new JsonMediaTypeFormatter();
formatter.SerializerSettings.Converters.Add(new ChildConverter());
var obj = await resp.Content.ReadAsAsync<T>(new MediaTypeFormatter[] {formatter});
于 2012-08-31T10:39:04.037 回答