0

以下のコードの実装を完了するのを手伝ってください。http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.htmlの例に従いました。この例は、多くのブログに掲載されています。

Web API アクションで抽象パラメーターを処理するための再利用可能な方法を見つけようとしています。Fiddler では完全に動作しますが、HttpClient 経由で Get を呼び出そうとすると、返される EntityNote が null になります。ReadJson メソッドが呼び出されることはないので、Create も呼び出されることはありません。ReadJson が呼び出される場所を理解するのに十分な Web API の流れを理解していないと思います。

Global.asax.cs

config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly;
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter());

リンクからのコンバーター (誰も WriteJson の実装方法を示していません)

public abstract class JsonCreationConverter<T> : JsonConverter
{
    protected abstract T Create(Type objectType, JObject jsonObject);

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsSubclassOf(typeof(T));
    }

    //This method never gets called
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var target = Create(objectType, jsonObject);
        serializer.Populate(jsonObject.CreateReader(), target);
        return target;
    }

    //I just kinda guessed at this code
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (this.CanConvert(value.GetType()))
        {
            serializer.Serialize(writer, value);
        }
    }
}

EntityNote は、実装として PortalProviderRefundNote を持つ抽象クラスです。

public class JsonDeviceConverter : JsonCreationConverter<EntityNote>
{
    //This method never gets called, because ReadJson is never called
    protected override EntityNote Create(Type objectType, JObject jsonObject)
    {
        var typeName = jsonObject["EntityNote"].ToString();
        switch (typeName)
        {
            case "PortalProviderRefundNote":
                return new PortalProviderRefundNote() { EntityId = 1 };
            default: return null;
        }
    }
}

HttpClient - チュートリアルでは JsonConvert.DeserializeObject を使用していますが、それがここにどのように適合するかわかりません... ReadAsAsync がこのタスクを実行します

//simplified **Suggested Edit**
this.jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
jsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter());

new HttpClient().GetAsync("http://localhost/api/EntityNotesController/").Result.Content.ReadAsAsync<EntityType>(new List<MediaTypeFormatter>(){ jsonFormatter }).Result;

サービスコントローラー

public EntityNote Get(int id)
{
    return new PortalProviderRefundNote() { EntityId = 1 };
}
4

2 に答える 2

1

クライアント側でも JsonMediaTypeFormatter で同じシリアライザー設定を変更する必要があります。

var jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
jsonFormatter.SerializerSettings.Converters.Add(new JsonDeviceConverter());

response.Content.ReadAsAsync<EntityNote>(new MediaTypeFormatter() { jsonFormatter }).Result;
于 2012-12-10T19:48:13.463 に答える
0

XML に切り替えて、KnownType 属性を使用しました。これはすぐに使用できます。JSONで解決策があるかどうか知りたいのですが、これで十分です。

于 2012-12-17T18:20:47.953 に答える