【问题标题】:How can I instruct Json.NET to convert an interface type to a concrete type without access to the serializer?如何指示 Json.NET 在不访问序列化程序的情况下将接口类型转换为具体类型?
【发布时间】:2012-08-31 07:59:01
【问题描述】:

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

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

下面的代码显示了一个 C# 控制台程序,它尝试将相同的 JSON 反序列化为首先是 Parent2 类,然后是 Parent1 类,指示 Json.NET 将 IChild1 接口类型转换为 Child1具体类型通过JsonConverterAttribute。对Parent2 的反序列化是有效的,因为我将ChildConverter 直接添加到serializer.Converters,而对Parent1 的反序列化会导致堆栈溢出异常,因为即使Child1 类型也会调用ChildConverter.Deserialize

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

【问题讨论】:

    标签: c# .net json serialization json.net


    【解决方案1】:

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

    var formatter = new JsonMediaTypeFormatter();
    formatter.SerializerSettings.Converters.Add(new ChildConverter());
    var obj = await resp.Content.ReadAsAsync<T>(new MediaTypeFormatter[] {formatter});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      相关资源
      最近更新 更多