C#如何阻止JSON请求体重复键自动移除或让请求失败
刚好遇到过类似的场景,给你两个针对性的解决方案,看你更倾向哪种需求:
方案一:让含重复键的请求直接失败
默认的JSON序列化器(不管是Newtonsoft.Json还是System.Text.Json)处理重复键时,要么自动保留最后一个,要么可以配置成遇到重复键就抛出异常。我们只需要调整序列化配置,就能让这类请求直接返回400错误。
如果你用的是Newtonsoft.Json(ASP.NET Core常用)
在Startup.cs或者Program.cs里配置Json选项,开启重复键报错:
services.AddControllers() .AddNewtonsoftJson(options => { // 遇到重复属性名时直接抛出异常 options.SerializerSettings.DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error; }) .AddOData(/* 你的OData配置 */);
如果你用的是System.Text.Json(.NET Core 3.0+ 默认)
同样在配置里关闭允许重复键:
services.AddControllers() .AddJsonOptions(options => { // 不允许JSON里出现重复的属性名,否则抛出异常 options.JsonSerializerOptions.AllowDuplicateNames = false; }) .AddOData(/* 你的OData配置 */);
配置完成后,当客户端传入含重复键的JSON时,序列化器会直接抛出异常,框架自动返回400 Bad Request,请求不会进入你的Func_Name方法。
方案二:保留所有重复键(不自动去重)
因为IDictionary<string, string>本身不允许重复键,所以默认绑定会自动去重。要保留重复键,得换一种接收方式:
方式1:改用List<KeyValuePair<string, string>>接收
直接修改请求参数的类型,让序列化器把所有键值对(包括重复的)转换成列表:
[HttpPost] [ODataRoute("some/odata/route")] public async Task<HttpResponseMessage> Func_Name(List<KeyValuePair<string, string>> request) { // 这里request会包含所有键值对,比如两个"Bob"的条目: // [("Bob", "Doctor"), ("Tim", "Engineer"), ("Bob", "Sailor")] // 后续业务逻辑可以自行处理重复键 ... }
注意:如果客户端传的是标准的对象格式JSON,Newtonsoft.Json和System.Text.Json都能自动把它解析成List<KeyValuePair>,不需要额外配置。
方式2:手动读取原始请求内容解析
如果需要更灵活的控制,可以直接读取原始请求体,用JsonTextReader遍历所有属性(包括重复的):
[HttpPost] [ODataRoute("some/odata/route")] public async Task<HttpResponseMessage> Func_Name() { // 读取原始请求内容 var rawJson = await Request.Content.ReadAsStringAsync(); var allKeyValuePairs = new List<KeyValuePair<string, string>>(); using (var reader = new JsonTextReader(new StringReader(rawJson))) { reader.DateParseHandling = DateParseHandling.None; while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { string key = reader.Value.ToString(); // 移动到属性值的位置 reader.Read(); string value = reader.Value?.ToString() ?? string.Empty; allKeyValuePairs.Add(new KeyValuePair<string, string>(key, value)); } } } // allKeyValuePairs现在包含所有重复的键值对 ... }
这种方式完全绕开了默认的模型绑定,能100%保留JSON里的所有键值对,适合需要精细处理的场景。
内容的提问来源于stack exchange,提问作者Renya Karasuma
相关产品推荐
相关产品推荐

