【发布时间】:2019-02-25 10:56:36
【问题描述】:
例如,我有带有字段 NameRegex 的 JSON:
{
"NameRegex": ".*abc+"
}
用户经常忘记“。”在“*”之前或犯类似错误。是否可以使用 json 模式验证此字段中指定的正则表达式的正确性?
【问题讨论】:
标签: .net json jsonschema
例如,我有带有字段 NameRegex 的 JSON:
{
"NameRegex": ".*abc+"
}
用户经常忘记“。”在“*”之前或犯类似错误。是否可以使用 json 模式验证此字段中指定的正则表达式的正确性?
【问题讨论】:
标签: .net json jsonschema
不幸的是,没有很好的方法来验证正则表达式,因为几乎任何字符串(甚至这个答案)都可能是有效的正则表达式。即使你有一个好的方法,正则表达式验证也是基于实现的,并且与 JSON Schema 的要求脱节。例如,我的实现(在.Net 中)将正则表达式处理委托给Regex 类。如果它失败了,那么你会得到一个运行时异常。
您实际上可以做的最好的事情是在部署到生产之前广泛测试您的正则表达式。
这里有几个不错的测试站点:
还有很多其他的。
【讨论】:
*abc+ 不是有效的正则表达式,因为在 * 之前没有什么可重复的
我不认为你可以使用 JSON 模式来做到这一点,但你可以在代码中通过挂钩到反序列化过程来做到这一点。在那里,您将通过尝试从中构造 Regex 对象来验证 NameRegex 字符串是否是有效的正则表达式,如果无效则抛出异常。
为此,请在目标类中创建一个接受 StreamingContext 的验证方法,并使用 [OnDeserialized] 属性对其进行装饰。用该方法编写您的验证代码。例如:
public class Foo
{
public string NameRegex { get; set; }
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
try
{
//ensure NameRegex is a valid regex
var r = new Regex(NameRegex);
}
catch
{
//throw whatever exception is appropriate for you
throw new InvalidDataException(
$"'{NameRegex}' is not a valid regular expression.");
}
}
}
如果验证失败,反序列化会抛出你定义的异常:
var foo = JsonConvert.DeserializeObject(
@"{""NameRegex"":""abc+""}",
typeof(Foo));
**** NameRegex 值 '*abc+' 不是有效的正则表达式 ****
【讨论】:
JSON 模式有一个注释关键字 format,一些验证器也会验证(根据规范,这是可选的)。
所以你可以说:
{
"type": "object",
"properties": {
"NameRegex": {
"type": "string",
"format": "regex"
}
}
}
但验证器不需要验证“格式”关键字。正如格雷格所提到的,即使您省略了* 前面的点,正则表达式通常仍然有效;它只是有不同的含义(重复星星前面的任何字符,而不是任何字符,零次或多次)
尽管使用 format 关键字仍然是一个好主意,因为它至少可以很好地记录您对该属性的意图,即使您的特定验证器不验证格式。
【讨论】: