0

请请请有人可以帮我完成下面的代码的实现。我按照http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.html上的示例进行操作。这个示例在很多博客上都发布了。

我试图找到一种可重用的方法来处理 Web API 操作中的抽象参数。它在 Fiddler 中完美运行,但是当我尝试通过 HttpClient 调用 Get 时返回的 EntityNote 为空。我发现 ReadJson 方法从来没有被调用过,所以 Create 也从来没有被调用过。我想我不太了解 Web API 的流程,无法理解应该在哪里调用 ReadJson。

全球.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 回答