1

私の問題は、JSONをインターフェイスタイプオブジェクトを含むタイプに逆シリアル化する必要があるため、そのインターフェイスタイプを変換する方法をJson.NETに指示する必要がありますが、Newtonsoft.Json.Deserializer直接制御することはできません。デシリアライズは、フレームワークコード、つまりHttpContent.ReadAsAsync<T>によって間接的に処理されます。

JsonSerializer.Convertersコンバータを直接追加することなく、インターフェイスタイプから具象タイプへの変換を指定するにはどうすればよいですか?インターフェイス定義で属性を使用する[JsonConverter]と、コンバータはインターフェイスの実装(つまり、変換先の具象型)も呼び出されます。

Parent2次のコードは、同じJSONを最初にクラスに、次にクラスに逆シリアル化しようとするC#コンソールプログラムを示していますParent1。Json.NETに、を介してIChild1インターフェイスタイプをChild1具象タイプに変換するように指示していますJsonConverterAttribute。に直接Parent2追加するため、への逆シリアル化は機能しますが、への逆シリアル化は、型に対しても呼び出されるため、スタックオーバーフロー例外が発生します。ChildConverterserializer.ConvertersParent1ChildConverter.DeserializeChild1

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>渡すことができます。JsonMediaTypeFormatterJsonConverterChildConverter

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 に答える