将Json反序列化为Asp.Net Web API中的派生类型

将Json反序列化为Asp.Net Web API中的派生类型,第1张

将Json反序列化为Asp.Net Web API中的派生类型

您不需要自定义模型活页夹。您也不需要考虑请求管道。

看看另一个SO:如何在JSON.NET中实现自定义JsonConverter以反序列化基类对象列表?。

我以此为基础来解决自己的问题。

JsonCreationConverter<T>
该SO中的引用开始(经过稍微修改以解决响应中类型序列化的问题):

public abstract class JsonCreationConverter<T> : JsonConverter{    /// <summary>    /// this is very important, otherwise serialization breaks!    /// </summary>    public override bool CanWrite    {        get        { return false;        }    }    /// <summary>     /// Create an instance of objectType, based properties in the JSON object     /// </summary>     /// <param name="objectType">type of object expected</param>     /// <param name="jObject">contents of JSON object that will be     /// deserialized</param>     /// <returns></returns>     protected abstract T Create(Type objectType, JObject jObject);    public override bool CanConvert(Type objectType)    {        return typeof(T).IsAssignableFrom(objectType);    }    public override object ReadJson(JsonReader reader, Type objectType,      object existingValue, JsonSerializer serializer)    {        if (reader.TokenType == JsonToken.Null) return null;        // Load JObject from stream         JObject jObject = JObject.Load(reader);        // Create target object based on JObject         T target = Create(objectType, jObject);        // Populate the object properties         serializer.Populate(jObject.CreateReader(), target);        return target;    }    public override void WriteJson(JsonWriter writer, object value,       JsonSerializer serializer)    {        throw new NotImplementedException();    }}

现在,您可以使用注释您的类型

JsonConverterAttribute
,将Json.Net指向自定义转换器:

[JsonConverter(typeof(MyCustomConverter))]public abstract class baseClass{  private class MyCustomConverter : JsonCreationConverter<baseClass>  {     protected override baseClass Create(Type objectType,        Newtonsoft.Json.Linq.JObject jObject)     {       //TODO: read the raw JSON object through jObject to identify the type       //e.g. here I'm reading a 'typename' property:       if("DerivedType".Equals(jObject.Value<string>("typename")))       {         return new DerivedClass();       }       return new DefaultClass();       //now the base class' pre will populate the returned object.     }  }}public class DerivedClass : baseClass {  public string DerivedProperty { get; set; }}public class DefaultClass : baseClass {  public string DefaultProperty { get; set; }}

现在,您可以将基本类型用作参数:

public Result Post(baseClass arg) {}

如果我们要发布:

{ typename: 'DerivedType', DerivedProperty: 'hello' }

然后

arg
是的实例
DerivedClass
,但是如果我们发布:

{ DefaultProperty: 'world' }

然后,您将获得的实例

DefaultClass

编辑-为什么我更喜欢这种方法
TypeNameHandling.Auto/All

我确实相信使用

TypeNameHandling.Auto/All
JotaBe支持的方法并非总是理想的解决方案。在这种情况下很可能会-
但是我个人不会这样做,除非:

  • 我的API 只会 由我或我的团队使用
  • 我不在乎具有兼容XML的双重终结点

使用Json.Net

TypeNameHandling.Auto
或时
All
,您的Web服务器将开始以格式发送类型名称
MyNamespace.MyType,MyAssemblyName

我在评论中说过,我认为这是一个安全问题。我从Microsoft阅读的一些文档中提到了这一点。似乎没有再提及,但是我仍然觉得这是一个合理的问题。我
从来

不想向外界公开名称空间限定的类型名称和程序集名称。它增加了我的攻击面。因此,是的,我无法拥有

Object
API类型的属性/参数,但是谁能说我网站的其余部分完全没有漏洞呢?谁说未来的端点不会暴露利用类型名称的能力?为什么仅仅因为它更容易而抓住这次机会?

另外-如果您正在编写“适当的” API,即专门为第三方使用而不仅仅是为自己使用,并且正在使用Web API,那么您很可能希望利用JSON /
XML内容类型处理(至少)。了解您尝试编写易于使用的文档的程度,该文档针对XML和JSON格式对所有API类型的引用有所不同。

通过重写JSON.Net如何理解类型名称,您可以将二者结合在一起,纯粹根据喜好在调用方的XML /
JSON之间进行选择,而不是因为类型名称更容易在一个或另一个中记住。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5567264.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存