OData – Custom Serialize & Deserialize

前言

本来计划用 Custom Serialize 来解决 OData 不支持 [JsonPropertyName] 的问题.

但是后来发现 Custom Serialize 并不能解决这个问题. Custom Serialize 允许我们在 response 的时候修改输出的 JSON

但是 $filter=name eq 'test', 在 parse odata query 的时候, JsonPropertyName 也是需要考虑到的.

而这个领域是无法通过 Custom Serialize & Deserialize 解决的, 所以我走错路了. 

但还是小小记入一下它吧.

参考:

Build formatter extensions in ASP.NET Core OData 8 and hooks in ODataConnectedService

Custom Serialize

做一个类并继承 ODataResourceSerializer

public class MyResourceSerializer : ODataResourceSerializer
{
    public MyResourceSerializer(IODataSerializerProvider serializerProvider)
        : base(serializerProvider)
    { }

    public override ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
    {
        ODataResource resource = base.CreateResource(selectExpandNode, resourceContext);
        resource.Properties.ToList().ForEach(p => p.Name = p.Name.ToUpper());
        return resource;
    }
}

Override 它的方法, 上面是一个把 property name to uppercase 的例子

接着还需要一个 SerializerProvider 来把上面的 MyResourceSerializer 提供出去

public class MySerializerProvider : ODataSerializerProvider
{
    public MySerializerProvider(IServiceProvider serviceProvider)
        : base(serviceProvider)
    { }

    public override IODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
    {
        if (edmType.IsEntity() || edmType.IsComplex())
        {
            return new MyResourceSerializer(this);
        }
        return base.GetEdmTypeSerializer(edmType);
    }
}

ODataSerializerProvider 内有对应不同类型的 serializer, 比如 Enum

依据需求替换掉对应的 Serializer.

最后是把这个 provider register to services provider.

Custom Deserialize

和 Serialize 一样, 做一个 deserialize class, 一个 provider, 让后 register to services provider.

public class MyResourceDeserializer : ODataResourceDeserializer
{
    public MyResourceDeserializer(IODataDeserializerProvider serializerProvider)
        : base(serializerProvider)
    { }

    public override object ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
    {
        object resource = base.ReadResource(resourceWrapper, structuredType, readContext);
        return resource;
    }
}

public class MyDeserializerProvider : ODataDeserializerProvider
{
    public MyDeserializerProvider(IServiceProvider serviceProvider)
        : base(serviceProvider)
    { }

    public override IODataEdmTypeDeserializer GetEdmTypeDeserializer(IEdmTypeReference edmType, bool isDelta = false)
    {
        if (edmType.IsEntity() || edmType.IsComplex())
        {
            return new MyResourceDeserializer(this);
        }

        return base.GetEdmTypeDeserializer(edmType, isDelta);
    }
}

题外话

[JsonPropertyName] 怎么弄?

Custom Serialize 无法解决 JsonPropertyName 的问题. 要解决它需要从 ODataConventionModelBuilder 入手.

要嘛改它内部实现, 要嘛直接改它做出来的 EdmModel. 我目前是暂时不去解决这个问题, 毕竟还没有需求.

原文地址:https://www.cnblogs.com/keatkeat/p/15640470.html