加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

序列化 – JSON.NET作为WebAPI 2 OData序列化程序与ODataMediaTy

发布时间:2020-12-16 19:49:06 所属栏目:百科 来源:网络整理
导读:我试图使用 JSON.NET作为WebAPI 2堆栈中的默认序列化程序.我已经实现了JsonMediaTypeFormatter,其中我已经使用JSON.NET serializer进行序列化/反序列化数据,并创建了JsonContentNegotiator来使用此媒体类型格式化程序.除了OData查询之外,所有功能都正常工作
我试图使用 JSON.NET作为WebAPI 2堆栈中的默认序列化程序.我已经实现了JsonMediaTypeFormatter,其中我已经使用JSON.NET serializer进行序列化/反序列化数据,并创建了JsonContentNegotiator来使用此媒体类型格式化程序.除了OData查询之外,所有功能都正常工作 – 如果我添加[Queryable]元数据操作方法,则响应对象不包含任何元数据信息,仅包含实体列表.

小例子我的行动方法:

[Queryable]
public async Task<PageResult<RuleType>> GetRuleType(ODataQueryOptions<RuleType> options)
{
    var ret = await _service.ListRuleTypesAsync(options);
    return new PageResult<RuleType>(
        ret,Request.GetNextPageLink(),Request.GetInlineCount());
}

如果我使用默认OData序列化,并按规则类型(例如 – … / odata / RuleType?$inlinecount = allpages& $skip = 0& $top = 1)调用某些查询,我将收到带有元数据信息的经典OData响应,计数属性:

odata.metadata ".../odata/$metadata#RuleType" 
odata.count    "2" 
value
        0    {
                 Id: 1
             Name: "General"
             Code: "General"
             Notes: null
             }

(有些字段被跳过,但是我的Notes属性为null值)
但是,如果我添加JsonContentNegotiator与JsonMediaTypeFormatter作为一个序列化程序 – 我只收到实体列表:

[
  {
    "Id": 1,"Name": "General","Code": "General"
  }
]

(没有Notes字段,因为NullValueHandling.Ignore)
更.如果我删除动作方法中的[Queryable]属性 – 我收到另一个结果:

{
  "Items": [
    {
      "Id": 1,"Code": "General"
    }
  ],"Count": 2
}

在这种情况下,我收到了Count,但是在这里仍然没有元数据. odata响应属性名称与默认值完全不同.

我的头脑正在吹起来我只想使用JSON.NET作为我的Web应用程序的任何部分的序列化程序(由于一些强大的限制).我该怎么做?

我已经弄清楚了我的问题,找到了解决方案. OData使用独立的媒体类型格式化器,从ODataMediaTypeFormatter继承. OData也使用不同的格式化器进行序列化和反序列化.为了替换这个行为,我们必须实现ODataDeserializerProvider和/或ODataSerializerProvider类的后代,并将这些类添加到HttpConfiguration.Formatters集合中
var odataFormatters = ODataMediaTypeFormatters
    .Create(new MyODataSerializerProvider(),new MuODataDeserializerProvider());
config.Formatters.AddRange(odataFormatters);

小反序列化提供商示例:

public class JsonODataDeserializerProvider : ODataDeserializerProvider
{
    public override ODataEdmTypeDeserializer GetEdmTypeDeserializer(IEdmTypeReference edmType)
    {
        var kind = GetODataPayloadKind(edmType);

        return new JsonODataEdmTypeDeserializer(kind,this);
    }

    private static ODataPayloadKind GetODataPayloadKind(IEdmTypeReference edmType)
    {
        switch (edmType.TypeKind())
        {
            case EdmTypeKind.Entity:
                return ODataPayloadKind.Entry;
            case EdmTypeKind.Primitive:
            case EdmTypeKind.Complex:
                return ODataPayloadKind.Property;
            case EdmTypeKind.Collection:
                IEdmCollectionTypeReference collectionType = edmType.AsCollection();
                return collectionType.ElementType().IsEntity() ? ODataPayloadKind.Feed : ODataPayloadKind.Collection;
            default:
                return ODataPayloadKind.Entry;
        }
    }

    public override ODataDeserializer GetODataDeserializer(IEdmModel model,Type type,HttpRequestMessage request)
    {
        var edmType = model.GetEdmTypeReference(type);

        return edmType == null ? null : GetEdmTypeDeserializer(edmType);
    }
}

ODataDeserializer:

public class JsonODataEdmTypeDeserializer : ODataEdmTypeDeserializer
{
    public JsonODataEdmTypeDeserializer(ODataPayloadKind payloadKind) : base(payloadKind)
    {
    }

    public JsonODataEdmTypeDeserializer(ODataPayloadKind payloadKind,ODataDeserializerProvider deserializerProvider) : base(payloadKind,deserializerProvider)
    {
    }

    public override object Read(ODataMessageReader messageReader,ODataDeserializerContext readContext)
    {
        var data = readContext.Request.Content.ReadAsStringAsync().Result;

        return JsonConvert.DeserializeObject(data,type);
    }
}

而且我也从WebAPI OData源代码添加了EdmLibsHelper类,在GetEdmTypeReference()和GetEdmType()方法的项目中,因为这个类是内部的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读