如何检测 Web API 发布请求 JSON 中的重复键

本文关键字:请求 JSON 何检测 检测 Web API 布请求 | 更新日期: 2023-09-27 18:37:17

当请求 Json 包含重复键时,我需要从 ASP.NET Web API Post 请求返回 400 错误。

例如,如果请求是

{
   "key1": "value1",
   "key2": 1000,
   "key2": 2000,
   "key3": "value3"
}

那么我希望由于有两个"key2"键而抛出错误。

我的控制器方法看起来像

[HttpPost]
public IHttpActionResult PostMethod([FromBody]RequestModel request)
{
   .....
}

和我的请求模型,例如

public class RequestModel
{
    [Required]
    public string Key1 {get; set; }
    [Required]
    public int Key2 {get; set; }
    public string Key3 {get; set; } 
}

在上面的示例中,Json 序列化程序似乎很乐意接受请求并使用 2000 填充 Key2,或者密钥的最后一个实例。

我想我需要做一些涉及 JsonSerializerSettings 类的事情,或者实现一个自定义的 JsonConverter,但我不确定如何继续。

如何检测 Web API 发布请求 JSON 中的重复键

这是一个自定义的 JsonConverter,当遇到重复的键时,它会抛出一个代码为 400 的HttpResponseException,Asp.Net Web API 应该自动处理它。

class DuplicateJsonConverter : JsonConverter
{
    public override bool CanWrite { get { return false; } }
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var paths = new HashSet<string>();
        existingValue = existingValue ?? Activator.CreateInstance(objectType, true);
        var backup = new StringWriter();
        using (var writer = new JsonTextWriter(backup))
            do
            {
                writer.WriteToken(reader.TokenType, reader.Value);
                if (reader.TokenType != JsonToken.PropertyName)
                    continue;
                if (string.IsNullOrEmpty(reader.Path))
                    continue;
                if (paths.Contains(reader.Path))
                       throw new HttpResponseException(HttpStatusCode.BadRequest); //as 400
                paths.Add(reader.Path);
            }
            while (reader.Read());
        JsonConvert.PopulateObject(backup.ToString(), existingValue);
        return existingValue;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

您应该使用此转换器装饰您的RequestModel类。

[JsonConverter(typeof(DuplicateJsonConverter))]
class RequestModel
{
  ''...
}

您可以创建一个拦截委托处理程序,该处理程序将在每次收到请求时触发。在其中,您可以获取发送到控制器的数据,并检查它是否有重复的键。创建的处理程序注册如下:

GlobalConfiguration.Configuration.MessageHandlers.Add(new YourDelegateHandler());