【发布时间】:2021-02-10 01:30:22
【问题描述】:
我有一个带有数据模型对象的 OData Api,该对象带有许多可为空的 DateTime 字段。
例如
public class Book : EntityBase
{
...
public DateTime? CreatedDate { get; set; }
public DateTime? UpdatedDate { get; set; }
...
}
使用 OData API 的客户端要求将 DateTime 字段格式化为“yyyy-MM-dd”格式,而不是像“yyyy-MM-ddTHH:mm:ss”这样的默认长格式
public class CustomODataSerializerProvider : DefaultODataSerializerProvider
{
private readonly CustomODataEntityTypeSerializer _entityTypeSerializer;
public CustomODataSerializerProvider(IServiceProvider rootContainer)
: base(rootContainer)
{
_entityTypeSerializer = new CustomODataEntityTypeSerializer(this);
}
public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
{
if (edmType.Definition.TypeKind == EdmTypeKind.Entity || edmType.Definition.TypeKind == EdmTypeKind.Complex)
return _entityTypeSerializer;
else
return base.GetEdmTypeSerializer(edmType);
}
}
public class CustomODataEntityTypeSerializer : ODataResourceSerializer
{
public CustomODataEntityTypeSerializer(ODataSerializerProvider provider)
: base(provider) { }
public override Microsoft.OData.ODataProperty CreateStructuralProperty(Microsoft.OData.Edm.IEdmStructuralProperty structuralProperty, ResourceContext resourceContext)
{
var property = base.CreateStructuralProperty(structuralProperty, resourceContext);
if (property.Name.Contains("Date"))
{
property.Value = ((DateTime)property.Value).ToShortDateString();
}
return property.Value != null ? property : null;
}
}
我也试过“property.Value = ((DateTimeOffset)property.Value).DateTime.ToShortDateString();”而不是上面的。
然后使用注册此序列化程序
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.EnableDependencyInjection();
endpoints.Select().Expand().OrderBy().Filter().Count().MaxTop(10);
endpoints.MapODataRoute("odata", "odata", a =>
{
a.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEdmModel), sp => GetEdmModel(app.ApplicationServices));
a.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataSerializerProvider), sp => new CustomODataSerializerProvider(sp));
});
//endpoints.MapODataRoute("odata", "odata", GetEdmModel(app.ApplicationServices));
});
但是当调用 OData 端点时出现此错误
can't parse JSON. Raw result:
{"@odata.context":"https://localhost:5000/odata/$metadata#Book","value":[
我也尝试应用 Json 序列化程序,但这对从 OData 端点提供的数据没有影响:
services
.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.IgnoreNullValues = false;
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-dd"));
}
}
我在 .NET Core 3.1 Web Api 中使用 Microsoft.AspNetCore.OData 7.4.1。任何有关如何更改通过 OData API 提供的数据的 DateTime 格式/序列化的建议将不胜感激。
【问题讨论】:
标签: datetime serialization odata asp.net-core-webapi jsonserializer