前言
本来计划用 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. 我目前是暂时不去解决这个问题, 毕竟还没有需求.