ASP.NET MVC中VirtualStock多类型JSON序列化异常解决问询
这个问题的核心原因很明确:你用Newtonsoft.Json成功完成了反序列化,但ASP.NET Core默认的Json()方法使用的是System.Text.Json,而System.Text.Json在处理object类型的属性时,无法正确识别它既可能是字符串又可能是复杂对象的情况,错误地将其当作集合处理,从而抛出了NotSupportedException。
下面给你三种可行的解决方案,按推荐程度排序:
方法一:让ASP.NET Core改用Newtonsoft.Json序列化返回结果(最推荐)
既然你已经在反序列化时使用了Newtonsoft.Json,直接让ASP.NET Core统一使用它来处理序列化,既能保持配置一致性,又能避免System.Text.Json的兼容性问题:
- 首先安装对应的NuGet包:
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
或者用.NET CLI:
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
- 在项目的服务配置中替换默认的Json序列化器:
- 如果你用的是.NET 6+的
Program.cs:
builder.Services.AddControllersWithViews() .AddNewtonsoftJson(options => { // 这里可以和你反序列化时的配置保持一致 options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore; // 其他你需要的Newtonsoft.Json配置都可以加在这里 });- 如果你用的是旧版的
Startup.cs:
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews() .AddNewtonsoftJson(options => { options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore; }); } - 如果你用的是.NET 6+的
这样配置后,Controller中的Json()方法就会使用Newtonsoft.Json来序列化结果,它能完美处理object属性既为字符串又为复杂对象的场景,和你反序列化时的逻辑完全一致。
方法二:为System.Text.Json编写自定义转换器
如果你不想切换到NewtonsoftJson,可以为VirtualStock属性编写一个自定义的JsonConverter,让System.Text.Json能正确识别两种类型:
- 先定义VirtualStock的对象类型:
public class VirtualStockObject { public string Value { get; set; } public bool IsAssigned { get; set; } }
- 编写自定义转换器:
public class VirtualStockConverter : JsonConverter<object> { public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 由于你已经用NewtonsoftJson做反序列化,这里的Read方法可以不用太关注 if (reader.TokenType == JsonTokenType.String) { return reader.GetString(); } else if (reader.TokenType == JsonTokenType.StartObject) { return JsonSerializer.Deserialize<VirtualStockObject>(ref reader, options); } return null; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { // 序列化时判断值的类型,分别处理 if (value is string stringValue) { writer.WriteStringValue(stringValue); } else if (value is VirtualStockObject objValue) { JsonSerializer.Serialize(writer, objValue, options); } else { writer.WriteNullValue(); } } }
- 在模型的
VirtualStock属性上标记这个转换器:
[JsonConverter(typeof(VirtualStockConverter))] public object? VirtualStock { get; set; }
这样System.Text.Json在序列化时就能正确识别VirtualStock的两种类型,不会再抛出异常。
方法三:修改模型为自定义联合类型(适合需要业务处理的场景)
如果你的业务逻辑需要区分VirtualStock是字符串还是对象,可以定义一个专门的类型来封装这两种情况:
public class VirtualStockWrapper { public string? StringValue { get; set; } public VirtualStockObject? ObjectValue { get; set; } // 辅助属性判断当前是哪种类型 public bool IsStringType => StringValue != null; } // 之前定义的VirtualStockObject public class VirtualStockObject { public string Value { get; set; } public bool IsAssigned { get; set; } }
然后修改模型中的属性:
public VirtualStockWrapper? VirtualStock { get; set; }
接着你需要在反序列化时用Newtonsoft.Json的自定义转换器来将原始的字符串或对象映射到这个Wrapper类中,这个方法相对复杂,适合需要对两种类型做不同业务处理的场景。
内容的提问来源于stack exchange,提问作者Mustafa Hamit

