jsonSchema 属性有条件地需要

Posted

技术标签:

【中文标题】jsonSchema 属性有条件地需要【英文标题】:jsonSchema attribute conditionally required 【发布时间】:2016-12-07 15:51:06 【问题描述】:

在 jsonSchema 中,您可以使用“required”属性来指示定义的字段是否为必填项:


    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": 
        "header": 
            "type": "object",
            "properties": 
                "messageName": 
                    "type": "string"
                ,
                "messageVersion": 
                    "type": "string"
                
            ,
            "required": [
                "messageName",
                "messageVersion"
            ]
        
    ,
    "required": [
        "header"
    ]

在某些情况下,我希望 messageVersion 字段不是强制性的。有没有办法使这个字段的强制性成为条件?

【问题讨论】:

是的,应该可以。数据中的哪些信息会触发强制性? @SarveswaranMeenakshiSundaram - 我不知道我只使用了 v4 的 json 架构 在版本 3 中这可能吗? 【参考方案1】:

根据您的情况,有几种不同的方法。我可以想到四种不同的方法来有条件地要求一个字段。

依赖关系

dependencies 关键字是required 关键字的条件变体。 dependencies 中的 foreach 属性,如果该属性存在于正在验证的 JSON 中,则与该键关联的架构也必须有效。 如果存在“foo”属性,则需要“bar”属性


  "type": "object",
  "properties": 
    "foo":  "type": "string" ,
    "bar":  "type": "string" 
  ,
  "dependencies": 
    "foo":  "required": ["bar"] 
  

如果架构仅包含 required 关键字,则还有一个短格式。


  "type": "object",
  "properties": 
    "foo":  "type": "string" ,
    "bar":  "type": "string" 
  ,
  "dependencies": 
    "foo": ["bar"]
  

含义

如果您的条件取决于字段的值,您可以使用称为蕴含的布尔逻辑概念。 “A 蕴含 B”实际上意味着,如果 A 为真,则 B 也必须为真。暗示也可以表示为“!A或B”。 “foo”属性不等于“bar”,或者“bar”属性是必需的。或者换句话说:如果“foo”属性等于“bar”,那么“bar”属性是必需的


  "type": "object",
  "properties": 
    "foo":  "type": "string" ,
    "bar":  "type": "string" 
  ,
  "anyOf": [
    
      "not": 
        "properties": 
          "foo":  "const": "bar" 
        ,
        "required": ["foo"]
      
    ,
     "required": ["bar"] 
  ]

如果“foo”不等于“bar”,#/anyOf/0 匹配并且验证成功。如果“foo”等于“bar”,#/anyOf/0 失败,#/anyOf/1 必须有效,anyOf 验证才能成功。

枚举

如果您的条件是基于一个枚举,它会更直接一点。 “foo”可以是“bar”或“baz”。如果“foo”等于“bar”,则需要“bar”。如果“foo”等于“baz”,则需要“baz”。


  "type": "object",
  "properties": 
    "foo":  "enum": ["bar", "baz"] ,
    "bar":  "type": "string" ,
    "baz":  "type": "string" 
  ,
  "anyOf": [
    
      "properties": 
        "foo":  "const": "bar" 
      ,
      "required": ["bar"]
    ,
    
      "properties": 
        "foo":  "const": "baz" 
      ,
      "required": ["baz"]
    
  ]

如果-那么-否则

JSON Schema (draft-07) 的一个相对较新的添加添加了 ifthenelse 关键字。 如果“foo”属性等于“bar”,则需要“bar”属性


  "type": "object",
  "properties": 
    "foo":  "type": "string" ,
    "bar":  "type": "string" 
  ,
  "if": 
    "properties": 
      "foo":  "const": "bar" 
    ,
    "required": ["foo"]
  ,
  "then":  "required": ["bar"] 

2017 年 12 月 23 日编辑:更新了暗示部分并添加了 If-Then-Else 部分。

编辑 06/04/2018: 修正 If-Then-Else 并更新单例 enums 以使用 const

【讨论】:

@scubbo 我不喜欢if-then-else 关键字,我拒绝使用它们。但是,如果您选择使用它,我建议始终将它们包装在仅包含这三个关键字的 allOf 中。 ...other_keywords..., "allOf": [ "if": ..., "then": ..., "else": ... ], ...more_keywords... @Jason 为什么不是if... 的粉丝?我认为在您的回答中对此提出简短的意见是完全合理的。还是说来话长? @ClayBridges 评论部分不适合讨论,但这里是简短版本。作为一般规则,JSON Schema 关键字是无状态的。除关键字值外,没有其他信息可用于验证实例。 ifthenelse 违反此规则,因为它们相互依赖。 @GGirard,这是我所知道的在 JSON Schema 中使用这些模式的最佳处理方式。布尔运算已正式记录在案,但其余的只是数学运算。 allOf == AND,anyOf == OR,oneOf == XOR,not == NOT。您可以在 google 上搜索“布尔代数”以获取有关数学方面的更多资源(例如蕴含)。 谷歌搜索条件 json 模式并被引导到这里。很棒的答案,用简单的例子涵盖了所有方面。做得好。 ?

以上是关于jsonSchema 属性有条件地需要的主要内容,如果未能解决你的问题,请参考以下文章

JSON Schema 是不是可以使用引用外部属性的 if/then/else

JSONSchema - 依赖于父属性的必需属性

JSON Schema 中的附加项和附加属性有啥区别?

有条件地在 knockout.js 中添加元素属性

有条件地在 JSF 组件标签中设置一个属性

插件 jsonschema2pojo:属性按要求显示,但它们应该是可选的