在 json 模式中验证 2 种可能的数据类型

Posted

技术标签:

【中文标题】在 json 模式中验证 2 种可能的数据类型【英文标题】:validate 2 possible types of data in jsonchema 【发布时间】:2019-04-11 04:09:42 【问题描述】:

我花了一整天的时间试图让它发挥作用,将发布一个参考列表和我在提问后尝试过的事情。

这是我的 jsonschema:


    "data": [
        "required": "effort",
        "decisive": "maybe",
        "field1": 7
    ,
    
        "required": "effort",
        "decisive": "no",
        "field1": 6
    ],
    "schema": 
        "$schema": "http://json-schema.org/draft-04/schema#",
        "type": "array",
        "items": 
            "type": "object",
            "properties": 
                "field1": 
                    "type": "string",
                    "pattern": "[A-Z]",
                    "title": "field1"
                ,
                "required": 
                    "type": "string",
                    "title": "required",
                    "readonly": true
                ,
                "decisive": 
                    "type": "string",
                    "title": "Decisive",
                    "enum": ["yes", "no", "maybe", "not now"]
                

            
        
    

考虑 jsonschema 的确切部分,但带有 field1 元素,如下所示:

"field1": 
    "type": "integer",
    "minimum": 5,
    "maximum": 10,
    "title": "field1"

第一个示例仅验证其字段中的大写字母1 第二个想要一个介于 5 和 10 之间的整数。

你如何让它验证其中任何一个,所以两者都被接受 -

或者只有大写字母 5 到 10 之间的整数?

哦 - 上面数据部分中的 field1 并不重要,它是所需的默认值。

我尝试过各种想法—— with oneOf - here, here, here

参数 - here

其他属性 - here

必填 - here

直观的做法是使用 oneOf on 模式,但正如许多问题中提到的那样,oneOf 在属性部分内不做任何事情,只是在它之外做任何事情。因此,我尝试在 oneOf 中拥有完全相同的属性,但只有一个区别,如上所述。这也不起作用,并且包含很多必须以某种方式避免的重复。

有谁知道如何解决这个问题?我没主意了..

【问题讨论】:

出于兴趣,这是某种任务还是工作?过去几天看到几个非常相似的问题? 它的工作。我认为每个人都在尝试将 jsonschema 用于表单,即使它不是为此而设计的。我现在有一个question with a bounty 试图将我们从羊驼中拯救出来,这样我们就可以更多地留在 Python 中。 【参考方案1】:

你是 oneOf 的正确方向之一,但你真正想要的是 anyOf。几乎每次你认为你想要oneOf,你真的想要anyOf。请记住,properties 的值与其他任何模式一样都是模式。您可以像在其他任何地方一样使用布尔关键字。


    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "array",
    "items": 
        "type": "object",
        "properties": 
            "field1": 
                "title": "field1"
                "anyOf": [
                    
                        "type": "string",
                        "pattern": "[A-Z]"
                    ,
                    
                        "type": "integer",
                        "minimum": 5,
                        "maximum": 10
                    
                ]
            ,
            "required": 
                "type": "string",
                "title": "required",
                "readonly": true
            ,
            "decisive": 
                "type": "string",
                "title": "Decisive",
                "enum": ["yes", "no", "maybe", "not now"]
            

        
    

编辑 1

当你听说oneOf 不能在属性内部使用时,他们正在谈论的就是这种事情。


  "type": "object",
  "properties": 
    "anyOf": [
      
        "field1":  ... 
      ,
      
        "field1":  ... 
      
    ],
    "required":  ... ,
    "decisive":  ... 
  

编辑 2

因为它出现在 cmets 中,所以这里更好地解释了为什么 oneOf 几乎从来都不是正确的选择。需要明确的是,oneOf 将始终代替 anyOf。如果anyOf 不存在,JSON Schema 不会失去任何表达能力。

但是,anyOf 是一个更精确的工具。当anyOf 可以使用oneOf 时,就像在工具箱中有一个简单的羊角锤时使用大锤敲钉子一样。

anyOf 是布尔或运算。 oneOf 是布尔“异或”(XOR) 操作。 “XOR”几乎没有用处,现代语言甚至不支持它。 OR 通常用运算符|| 表示。 XOR 没有类比。

anyOf 表示任何项都可以为真。 oneOf 表示只有一个项可以为真。当您使用oneOf 时,验证器需要测试所有 模式,以确保一个模式验证为真,其余的验证为假。当您使用anyOf 时,验证器可以在找到验证为真的模式后立即停止。这称为“短路”,所有现代编程语言在评估 OR 操作时都会这样做。当模式是互斥的(它们几乎总是如此)时,在找到一个模式后继续验证模式纯粹是浪费,因此应该避免。

我认为oneOf 被过度使用了,因为从自然语言的角度来看,它听起来是对的。

【讨论】:

虽然这个模式可以工作,但我不确定你为什么认为oneOf 不是正确的解决方案。 @cardamom 如果您使用此模式但将anyOf 替换为oneOf,会发生什么情况?它的行为仍然符合您的预期吗?在这种情况下,它应该可以,但 anyOfoneOf 在其他情况下的行为会有所不同。 @JasonDesrosiers 感谢您的回答。 @Relequestual 我仍然在努力让一切都在羊驼表单验证中工作,但如果你们都认为这应该工作,问题可能是别的。问another 羊驼问题。我不明白的是,anyOfinside 属性,所有内容都告诉我们不要这样做,例如 this 和 this。充满矛盾…… 伙计们,谢谢,它有效!如果我使用 Python 库 fastjsonschema 运行它,它会进行完全正确的验证。羊驼身上有某种虫子。需要知道该怪谁.. @cardamom 那些关于anyOf insdie 属性的链接...您所看到的是,properties 对象的任何键都与 JSON 实例中的键相关。 properties 对象中每个键的值是一个 JSON 模式。因此,您上面的内容是可以的。有意义吗? 文档中没有任何内容表明 alpaca.js 支持来自 JSON Schema 的 anyOf 或任何 *Of 关键字。 JSON Schema 不是为创建表单而设计的,因此生成表单的库倾向于按照他们认为合适的方式做自己的事情。有github问题。

以上是关于在 json 模式中验证 2 种可能的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中针对 XSD 模式验证 json 数据

如何验证 REST 服务中的传入 JSON 数据?

PostgreSQL 中的 JSON 模式验证?

如何验证集合的类型?

玩 2.4 参数化代数数据类型 JSON 验证

用于数据描述、数据验证和输入验证的 JSON 模式