如何在C# Minimal API返回的JSON中自动添加类名为type属性?
自动为C# Minimal API返回的JSON添加type属性
解决方案:自定义JSON转换器工厂
要实现无需在每个类中手动添加Type属性,通过配置System.Text.Json序列化器自动注入type字段,可以通过自定义JsonConverterFactory实现,具体步骤如下:
1. 实现转换器工厂与具体转换器
创建通用转换器工厂,拦截自定义类的序列化过程,自动添加type字段:
using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; public class TypePropertyConverterFactory : JsonConverterFactory { public override bool CanConvert(Type typeToConvert) { // 仅处理自定义类,排除基本类型、字符串、枚举、匿名类型等 return !typeToConvert.IsPrimitive && typeToConvert != typeof(string) && !typeToConvert.IsEnum && !typeToConvert.IsAnonymousType(); } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var converterType = typeof(TypePropertyConverter<>).MakeGenericType(typeToConvert); return (JsonConverter)Activator.CreateInstance(converterType)!; } } // 辅助扩展方法:判断是否为匿名类型 public static class TypeExtensions { public static bool IsAnonymousType(this Type type) { return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false) && type.IsGenericType && type.Name.Contains("AnonymousType") && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$")) && type.Attributes.HasFlag(TypeAttributes.NotPublic); } } // 具体类型的转换器 public class TypePropertyConverter<T> : JsonConverter<T> { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 反序列化时忽略type字段,正常解析原有属性 return JsonSerializer.Deserialize<T>(ref reader, options)!; } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { writer.WriteStartObject(); // 序列化对象原有属性(移除当前转换器避免递归调用) var modifiedOptions = new JsonSerializerOptions(options); modifiedOptions.Converters.RemoveAll(c => c.GetType() == typeof(TypePropertyConverter<T>)); JsonSerializer.Serialize(writer, value, modifiedOptions); // 添加type字段,值为当前类的名称 writer.WriteString("type", typeof(T).Name); writer.WriteEndObject(); } }
2. 配置Minimal API的JSON序列化器
在WebApplication.CreateBuilder阶段,将自定义转换器添加到JsonOptions中:
var builder = WebApplication.CreateBuilder(args); builder.Services.Configure<JsonOptions>(options => { options.SerializerOptions.Converters.Add(new TypePropertyConverterFactory()); }); var app = builder.Build(); // 示例API端点 app.MapGet("/user", () => new User { Name = "Jason" }); app.Run();
3. 测试效果
定义无需手动添加Type属性的User类:
public class User { public string Name { get; set; } }
调用/user端点后,返回的JSON将自动包含type字段:
{ "name": "Jason", "type": "User" }
扩展:自定义type字段的值
如果需要指定type字段的自定义值(而非类名),可通过自定义特性实现:
- 定义特性类:
[AttributeUsage(AttributeTargets.Class)] public class JsonTypeAttribute : Attribute { public string TypeName { get; } public JsonTypeAttribute(string typeName) => TypeName = typeName; }
- 在实体类上标记特性:
[JsonType("CustomUser")] public class User { public string Name { get; set; } }
- 修改转换器的
Write方法,读取特性值:
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { writer.WriteStartObject(); var modifiedOptions = new JsonSerializerOptions(options); modifiedOptions.Converters.RemoveAll(c => c.GetType() == typeof(TypePropertyConverter<T>)); JsonSerializer.Serialize(writer, value, modifiedOptions); // 优先读取自定义特性的TypeName,否则用类名 var typeAttr = typeof(T).GetCustomAttribute<JsonTypeAttribute>(); var typeName = typeAttr?.TypeName ?? typeof(T).Name; writer.WriteString("type", typeName); writer.WriteEndObject(); }
此时返回的JSON将是:
{ "name": "Jason", "type": "CustomUser" }
内容的提问来源于stack exchange,提问作者devil_inside
相关产品推荐
相关产品推荐

