检查 JSON 中的重复属性

Posted

技术标签:

【中文标题】检查 JSON 中的重复属性【英文标题】:check for duplicate properties in JSON 【发布时间】:2021-08-27 20:14:09 【问题描述】:

我们正在开发一个基于 .Net 核心的 Web api 应用程序,为此我们需要针对基于 c# 的类型验证传入的请求主体,该请求主体是 JSON 格式。 我们此时正在评估NJsonSchema 库以查看它是否会引发重复属性错误。 但看起来它不支持此验证。我们还检查了来自 NewtonSoftJSON 架构验证器,但似乎它也不支持重复的属性验证。

下面是我们使用的使用NJsonSchema的最小化代码-

using NewtonSoft.Json;
public class MyRequest
    
        [JsonRequired]
        [JsonProperty("name")]
        public string Name  get; set; 

当我们像这样传递一个 JSON 对象时 -

"name":"abc","name":"xyz"

我们需要我们的 JSON 验证器来为 duplicate property 抛出错误 我们的示例测试如下所示 -

[Test]
        public async System.Threading.Tasks.Task SchemaValidation_WithDuplicateProperty_Async()
        
            var jsonString = await File.ReadAllTextAsync("Data//JsonWithDuplicateProperty.json");
            var schema = JsonSchema.FromType<MyRequest>();
            var errors = schema.Validate(jsonString);
            Assert.That(errors.Count(), Is.EqualTo(1));
        

所以我的问题 - 过去有没有人这样做过?或者是否有任何.net core 的库为重复属性提供JSON 验证和/或可以使用NJsonSchemaNewtonSoft 来完成。

【问题讨论】:

有趣的是,根据RFC7159,它是合法的。它说:对象中的名称应该是唯一的。 另外值得一提的是,JamesNK 说“Json.NET 中没有办法限制它们。它将使用最后一个值。”,很有趣顺便问一下。 进一步看,似乎使用JsonLoadSettings 可能会有所帮助,并且在这种情况下专门设置DuplicatePropertyNameHandling seems to throw。 【参考方案1】:

正如@zaggler 所说,使用Newtonsoft,您可以使用DuplicatePropertyNameHandling 枚举。不幸的是,您不能直接在对DeserializeObject 的调用中使用它(在JsonSerializerSettings 中);它必须在 JToken Reader 中使用。有关详细信息,请参阅此讨论主题:

https://github.com/JamesNK/Newtonsoft.Json/issues/931

这是一种以DeserializeObject-esque 方式包装动作的方法:

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
                    
public class Program

    public static void Main()
    
        var json = @"""name"":""abc"",""name"":""xyz""";

        var objA = DeserializeObject<MyRequest>(json, new JsonSerializerSettings(), DuplicatePropertyNameHandling.Ignore);
        Console.WriteLine(".Ignore: " + objA.Name);
        
        var objB = DeserializeObject<MyRequest>(json, new JsonSerializerSettings(), DuplicatePropertyNameHandling.Replace);
        Console.WriteLine(".Replace: " + objB.Name);
        
        var objC = DeserializeObject<MyRequest>(json, new JsonSerializerSettings(), DuplicatePropertyNameHandling.Error);
        Console.WriteLine(".Error: " + objC.Name); // throws error before getting here

    public static T DeserializeObject<T>(string json, JsonSerializerSettings settings, DuplicatePropertyNameHandling duplicateHandling)
    
        JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
        using (var stringReader = new StringReader(json))
        using (var jsonTextReader = new JsonTextReader(stringReader))
        
            jsonTextReader.DateParseHandling = DateParseHandling.None;
            JsonLoadSettings loadSettings = new JsonLoadSettings  
                DuplicatePropertyNameHandling = duplicateHandling
            ;
            var jtoken = JToken.ReadFrom(jsonTextReader, loadSettings);
            return jtoken.ToObject<T>(jsonSerializer);
        
    

public class MyRequest
    
        [JsonRequired]
        [JsonProperty("name")]
        public string Name  get; set; 

输出:

.忽略:abc

.替换:xyz

运行时异常(第 31 行):属性 当前 JSON 对象中已存在名称“名称”。小路 'name',第 1 行,第 21 位。

见:

https://dotnetfiddle.net/EfpzZu

【讨论】:

以上是关于检查 JSON 中的重复属性的主要内容,如果未能解决你的问题,请参考以下文章

使用嵌套对象中的属性反序列化 JSON [重复]

从数组中的 JSON 对象中删除属性 [重复]

AngularJS 表单。 JSON中的可选属性[重复]

Jackson中的JSON属性文件不区分大小写[重复]

JSON和JS重复检查索引号(PURE JAVASCRIPT)

jQuery hasAttr 检查元素上是不是有属性[重复]