如何在模型或LINQ查询中格式化API控制器输出的日期与小数
问题描述
DateTime格式化问题
我有一个返回JSON结果供无限滚动插件使用的API控制器,无法通过插件本身格式化输出,必须在传给控制器前确保输出格式正确。尝试在模型中添加[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]特性,但并未生效;在LINQ查询的select子句中把Date = p.Date改成Convert.ToDateTime(p.Date).ToString("dddd MMMM dd, yyyy")会出现无法隐式转换字符串与日期类型的问题,而这种写法在视图中是可行的。
小数(价格)格式化问题
价格字段应保留两位小数,但控制器的JSON输出仅保留用户输入的位数,导致出现$20.5、$0、$22.55这类不一致的结果。价格模型定义如下:
[Required(ErrorMessage = "Price Required!")] [Range(.00, Double.PositiveInfinity, ErrorMessage = "Must Be Positive Number!")] [Display(Name = "Price:")] [DataType(DataType.Currency)] [Column(TypeName = "decimal(18, 2)")] public decimal? Price { get; set; }
解决方案
针对DateTime字段的JSON格式化
方法1:使用序列化特性(Newtonsoft.Json)
在模型的DateTime字段上直接添加序列化特性,指定输出格式:
using Newtonsoft.Json; using Newtonsoft.Json.Converters; [JsonConverter(typeof(IsoDateTimeConverter), "dddd MMMM dd, yyyy")] // 若需要MM/dd/yyyy格式,替换为"MM/dd/yyyy" public DateTime? Date { get; set; }
方法2:全局配置序列化规则(ASP.NET Core)
在Program.cs中配置全局日期序列化格式,所有DateTime类型字段会统一应用该规则:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new CustomDateTimeConverter("dddd MMMM dd, yyyy")); }); // 自定义日期转换器 public class CustomDateTimeConverter : JsonConverter<DateTime?> { private readonly string _format; public CustomDateTimeConverter(string format = "MM/dd/yyyy") { _format = format; } public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { DateTime.TryParse(reader.GetString(), out var date); return date; } public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) { writer.WriteStringValue(value?.ToString(_format)); } }
方法3:LINQ查询投影处理
在查询时直接将日期字段格式化为字符串,返回匿名类避免类型转换错误:
var data = dbContext.YourEntities .Select(p => new { Date = p.Date.HasValue ? p.Date.Value.ToString("dddd MMMM dd, yyyy") : null, // 其他需要返回的字段 }) .ToList(); return Ok(data);
针对小数(Price)字段的JSON格式化
方法1:使用序列化特性
在Price字段上添加自定义转换器,强制保留两位小数:
public class CustomDecimalConverter : JsonConverter<decimal?> { public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { decimal.TryParse(reader.GetString(), out var price); return price; } public override void Write(Utf8JsonWriter writer, decimal? value, JsonSerializerOptions options) { writer.WriteStringValue(value?.ToString("F2")); // F2表示保留两位小数 } } // 模型中应用 [JsonConverter(typeof(CustomDecimalConverter))] [Column(TypeName = "decimal(18, 2)")] public decimal? Price { get; set; }
方法2:全局配置小数序列化规则
在Program.cs中全局配置,所有decimal类型字段统一保留两位小数:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new CustomDecimalConverter()); });
方法3:LINQ查询投影处理
在查询时直接格式化Price字段为字符串:
var data = dbContext.YourEntities .Select(p => new { Price = p.Price.HasValue ? p.Price.Value.ToString("F2") : null, // 其他需要返回的字段 }) .ToList(); return Ok(data);
内容的提问来源于stack exchange,提问作者BigTechCensorVictim
相关产品推荐
相关产品推荐

