使用 json-schema 来要求或禁止基于另一个属性值的属性?

Posted

技术标签:

【中文标题】使用 json-schema 来要求或禁止基于另一个属性值的属性?【英文标题】:Use json-schema to require or disallow properties based on another property value? 【发布时间】:2018-10-24 17:49:00 【问题描述】:

我要在 json-schema 中完成的工作:当属性 enabledtrue 时,应该需要某些其他属性。当false 时,应该禁止这些属性。

这是我的 json 模式:


  "type": "object",
  "properties": 
    "enabled":  "type": "boolean" 
  ,
  "required" : ["enabled"],
  "additionalProperties" : false,
  "if": 
    "properties": 
      "enabled": true
    
  ,
  "then":  
    "properties": 
      "description" :  "type" : "string" ,
      "count":  "type": "number" 
    ,
    "required" : ["description", "count"]
  

使用ajv 6.5 版进行验证,无论enabled 的值如何,都需要count 等。例如,对于数据:

 "enabled": false 

我的验证错误是:

[  keyword: 'required',
    dataPath: '',
    schemaPath: '#/then/required',
    params:  missingProperty: 'description' ,
    message: 'should have required property \'description\'' ,
   keyword: 'required',
    dataPath: '',
    schemaPath: '#/then/required',
    params:  missingProperty: 'count' ,
    message: 'should have required property \'count\'' ,
   keyword: 'if',
    dataPath: '',
    schemaPath: '#/if',
    params:  failingKeyword: 'then' ,
    message: 'should match "then" schema'  ]

如何使用 json-schema draft-7 完成此操作?

请注意,此问题与 jsonSchema attribute conditionally required 类似,但要求更严格。

【问题讨论】:

jsonSchema attribute conditionally required的可能重复 @Jason 不是重复的。大同小异,只是这个问题要求更严格。 我不同意。这是标记为“Enum”的策略的一个非常简单的用例。实际上,您在下面的答案使用了该策略。您的答案应标记为已接受的答案。这比if-then-else 的答案好多了。 我同意接受我自己的答案(在 5 小时内),因为这可能是解决我问题的更优雅的方法。我认为这个问题不是重复的,因为它提出了一个不同的(如果相关的话)问题。我不止一次阅读了您对另一个问题的(优秀)答案,但仍然不知道如何解决我/这个特定问题。虽然这里的“枚举”策略变体的适用性对于熟练的从业者 来说可能是显而易见的,但作为新手,我可以说这对我来说并不明显。最好为这个案子写清楚,以可能拯救其他挣扎的人。 【参考方案1】:

为此,您需要在if 语句中使用const 关键字,因此架构将如下所示:


  "type": "object",
  "properties": 
    "enabled":  "type": "boolean" 
  ,
  "required" : ["enabled"],
  "additionalProperties" : false,
  "if": 
    "properties": 
      "enabled": "const": true
    
  ,
  "then":  
    "properties": 
      "description" :  "type" : "string" ,
      "count":  "type": "number" 
    ,
    "required" : ["description", "count"]
  

【讨论】:

【参考方案2】:

这受到 vearutop 出色回答的启发。我认为它可能会更短一些,并且可以实现我的既定目的。


  "type": "object",
  "oneOf" : [
    
      "properties": 
        "enabled":  "const": false 
      ,
      "required": ["enabled"],
      "additionalProperties": false
    ,
    
      "properties": 
        "enabled":  "const": true ,
        "description":  "type": "string" ,
        "count":  "type": "number" 
      ,
      "required": [ "enabled", "description", "count"],
      "additionalProperties": false
    
  ]

正如 cmets 中所指出的,这是 this answer 中阐明的 Enum 策略的特定变体。

【讨论】:

【参考方案3】:

试试这个架构:


  "type": "object",
  "properties": 
    "enabled": 
      "type": "boolean"
    
  ,
  "required": [
    "enabled"
  ],
  "if": 
    "properties": 
      "enabled": 
        "const": true
      
    
  ,
  "then": 
    "properties": 
      "enabled": 
        "type": "boolean"
      ,
      "description": 
        "type": "string"
      ,
      "count": 
        "type": "number"
      ,
      "additionalProperties": false
    ,
    "required": [
      "description",
      "count"
    ]
  ,
  "else": 
    "properties": 
      "enabled": 
        "type": "boolean"
      
    ,
    "additionalProperties": false
  

如果您需要"additionalProperties": false,您必须枚举thenelse 中的所有属性。如果您可以接受其他属性,则架构可能会更简单:


  "type": "object",
  "properties": 
    "enabled": 
      "type": "boolean"
    
  ,
  "required": [
    "enabled"
  ],
  "if": 
    "properties": 
      "enabled": 
        "const": true
      
    
  ,
  "then": 
    "properties": 
      "description": 
        "type": "string"
      ,
      "count": 
        "type": "number"
      
    ,
    "required": [
      "description",
      "count"
    ]
  

我检查过ajv cli。

有效:"enabled": false

无效:"enabled": true

有效:"enabled": true, "description":"hi", "count":1

【讨论】:

以上是关于使用 json-schema 来要求或禁止基于另一个属性值的属性?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSON-Schema 定义模式并使用 Mongoose?

如何禁止搜索引擎收录的方法

使用json-schema校验json数据

WPF 根据指定条件显示或禁止listView中的每一项的右键菜单

如何从 Swagger API 声明生成 JSON-Schema

雪上加霜!谷歌或禁止中兴手机采用Android系统