【问题标题】:Validate JSON against JSON Schema C#根据 JSON Schema C# 验证 JSON
【发布时间】:2013-10-23 14:13:20
【问题描述】:

有没有办法针对该结构的 JSON 模式来验证 JSON 结构?我查看并发现 JSON.Net validate 但这并不能满足我的要求。

JSON.net 会:

JsonSchema schema = JsonSchema.Parse(@"{
  'type': 'object',
  'properties': {
    'name': {'type':'string'},
    'hobbies': {'type': 'array'}
  }
}");

JObject person = JObject.Parse(@"{
  'name': 'James',
  'hobbies': ['.NET', 'LOLCATS']
}");

bool valid = person.IsValid(schema);
// true

这验证为真。

JsonSchema schema = JsonSchema.Parse(@"{
  'type': 'object',
  'properties': {
    'name': {'type':'string'},
    'hobbies': {'type': 'array'}
  }
}");

JObject person = JObject.Parse(@"{
  'surname': 2,
  'hobbies': ['.NET', 'LOLCATS']
}");

bool valid = person.IsValid(schema);

这也验证为真

JsonSchema schema = JsonSchema.Parse(@"{
  'type': 'object',
  'properties': {
    'name': {'type':'string'},
    'hobbies': {'type': 'array'}
  }
}");

JObject person = JObject.Parse(@"{
  'name': 2,
  'hobbies': ['.NET', 'LOLCATS']
}");

bool valid = person.IsValid(schema);

只有这个验证为假。

理想情况下,我希望它验证那里没有不应该存在的字段,即 name,即 surname

【问题讨论】:

  • 您想验证字符串(模式)与字符串(给定对象)还是使用对象作为模式?
  • 是的,像 SCHEMA ...{'Name' : string , 'Cars': int ....} vs OBJ ...{'Name' : Bob, 'Pants': 2....} 是假的,但 ...{'Name' : Bob, ....} 是真的。我会得到一个 JSON 字符串,我需要将它与数据库中的模式进行比较以确保它是有效的。
  • 再次我想问得更清楚一点,是否该架构是您拥有的 C# 对象并且您想针对传入的未知字符串对其进行测试?
  • 我不确定我是否理解正确,但这里是:我输入了一个未知字符串,我想将它与我拥有的模式字符串进行比较。这听起来像是你在问什么。

标签: c# json validation jsonschema


【解决方案1】:

我认为你只需要添加

'additionalProperties': false

到您的架构。这将停止提供未知属性。

所以现在你的结果将是:- True, False, False

测试代码....

void Main()
{
var schema = JsonSchema.Parse(
@"{
    'type': 'object',
    'properties': {
        'name': {'type':'string'},
        'hobbies': {'type': 'array'}
    },
    'additionalProperties': false
    }");

IsValid(JObject.Parse(
@"{
    'name': 'James',
    'hobbies': ['.NET', 'LOLCATS']
  }"), 
schema).Dump();

IsValid(JObject.Parse(
@"{
    'surname': 2,
    'hobbies': ['.NET', 'LOLCATS']
  }"), 
schema).Dump();

IsValid(JObject.Parse(
@"{
    'name': 2,
    'hobbies': ['.NET', 'LOLCATS']
  }"), 
schema).Dump();
}

public bool IsValid(JObject obj, JsonSchema schema)
{
    return obj.IsValid(schema);
}

输出:-

True
False
False

您还可以在必须提供的字段中添加 "required":true,这样您就可以返回包含缺失/无效字段详细信息的消息:-

Property 'surname' has not been defined and the schema does not allow additional     properties. Line 2, position 19. 
Required properties are missing from object: name. 

Invalid type. Expected String but got Integer. Line 2, position 18. 

【讨论】:

  • 目前不鼓励使用“additionalProperties”,而是使用“propertyNames”(自draft-06 起)。它将完成完全相同的工作(仅允许具有符合模式的 enum cor 中列出的键的属性)。另请参阅:json-schema.org/understanding-json-schema/reference/… 并考虑:"propertyNames" : { "enum" : ["name", "hobbies"] } 在您的架构中,而不是“additionalProperties”。
【解决方案2】:

好的,我希望这会有所帮助。

这是你的架构:

 public class test
{
    public string Name { get; set; }
    public string ID { get; set; }

}

这是你的验证器:

/// <summary>
    /// extension that validates if Json string is copmplient to TSchema.
    /// </summary>
    /// <typeparam name="TSchema">schema</typeparam>
    /// <param name="value">json string</param>
    /// <returns>is valid?</returns>
    public static bool IsJsonValid<TSchema>(this string value)
        where TSchema : new()
    {
        bool res = true;
        //this is a .net object look for it in msdn
        JavaScriptSerializer ser = new JavaScriptSerializer();
        //first serialize the string to object.
        var obj = ser.Deserialize<TSchema>(value);

        //get all properties of schema object
        var properties = typeof(TSchema).GetProperties();
        //iterate on all properties and test.
        foreach (PropertyInfo info in properties)
        {
            // i went on if null value then json string isnt schema complient but you can do what ever test you like her.
            var valueOfProp = obj.GetType().GetProperty(info.Name).GetValue(obj, null);
            if (valueOfProp == null)
                res = false;
        }

        return res;
    }

而使用方法是:

string json = "{Name:'blabla',ID:'1'}";
        bool res = json.IsJsonValid<test>();

如果您有任何问题,请提出,希望对您有所帮助,请考虑到这不是没有异常处理等的完整代码......

【讨论】:

  • 您好,感谢您的回复。问题是(据我了解您的代码是如何工作的,如果我的理解有误或有其他方法请解释)我们没有 shcema 的 C# 类/对象。它是存储在数据库中的模式字符串。可能有很多很多不同的模式,所以我们不能为它们都创建对象。
  • 这就是为什么我问架构是否只是字符串还是可以是对象,我会尝试进行更改以满足您的需求。
  • @ShaunGroenewald 嘿抱歉最近有很多时间,问题解决了吗?
  • 嗨,不,我还没有解决它。我正在尝试对两个字符串进行字符串/正则表达式查找和比较。
  • 是的,但我现在有点卡住了。我的想法是对 key:value 进行正则表达式匹配并将其放入一个列表中,然后将这两个列表相互比较(如果传入的 json 键名与架构中的任何一个都不匹配,则它是无效的)
【解决方案3】:

我只是添加简短的答案,使用来自 Newtonsoft.Json.Schema 的 JSchemaGenerator

 public static bool IsJsonValid<TSchema>>(string value)
    {
        JSchemaGenerator generator = new JSchemaGenerator();
        JSchema schema = generator.Generate(typeof(TSchema));
        schema.AllowAdditionalProperties = false;           

        JObject obj = JObject.Parse(value);
        return obj.IsValid(schema);
    }

【讨论】:

    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-27
    • 2021-04-18
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多