如何基于另一个属性中的枚举值执行JSON模式属性验证

时间:2020-04-11 23:06:43

标签: json jsonschema

基于给定的JSON模式,如果我必须基于DayHeader中选择的“ Day”为“ DayActivity”构建“ required”(例如,如果Day为SUNDAY,则仅需要PhysicalActivity),如何构建JSON模式?我尝试了各种方法,例如if else else和定义。当我基于JSON模式生成JSON文件时,它无法验证“ Day”属性选择的必需“ DayActivity”。 基本上,我如何引用在其他属性中选择的值并构建“必需”?感谢有关此问题的任何参考。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "DayHeader": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "Day": {
          "type": "string",
          "enum": [
            "SUNDAY",
            "MONDAY",
            "TUESDAY",
            "WEDNESDAY",
            "THURSDAY",
            "FRIDAY",
            "SATURDAY"
          ]
        }
      },
      "required": [
        "day"
      ]
    },
    "ActivityDetail": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "DayActivity": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "PhysicalActivity": {
                "type": "string",
                "enum": [
                  "Walking",
                  "Running"
                ]
              },
              "StudyActivity": {
                "type": "string",
                "enum": [
                  "Maths Class",
                  "Science Class"
                ]
              },
              "ArtActivity": {
                "type": "string",
                "enum": [
                  "Drawing",
                  "Dance"
                ]
              }
            }
          }
        }
      }
    }
  }
}

1 个答案:

答案 0 :(得分:0)

通常来说,这个问题已经有了一个很棒的通用答案here

话虽这么说,您也许可以针对"DayActivity"改善数据结构,这也将使制定相应的JSON模式更加容易。


您的"DayActivity"当前是一个对象数组,每个对象同时最多包含三个属性:"PhysicalActivity" / "StudyActivity" / "ArtActivity"。相反,如下所示,它只允许三个属性之一出现在单个数组项中:

"DayActivity": {
  "type": "array",
  "minItems": 1,
  "items": {
    "type": "object",
    "oneOf": [
      {
        "properties": {
          "PhysicalActivity": {
            "type": "string",
            "enum": ["Walking", "Running"]
          }
        },
        "required": ["PhysicalActivity"]
      },
      {
        "properties": {
          "StudyActivity": {
            "type": "string",
            "enum": ["Maths Class", "Science Class"]
          }
        },
        "required": ["StudyActivity"]
      },
      {
        "properties": {
          "ArtActivity": {
            "type": "string",
            "enum": ["Drawing", "Dance"]
          }
        },
        "required": ["ArtActivity"]
      }
    ]
  },
  "contains": {
    "required": ["PhysicalActivity"]
  }
}

最后请注意"contains"关键字,以确保在"PhysicalActivity"数组中始终始终至少有一个"DayActivity"条目。

如果您现在想在每个工作日(但"StudyActivity")有条件地强制执行"SUNDAY",则可以在主模式中添加以下内容(即在顶层"properties": { "DayHeader": ... }声明:

"oneOf": [
  {
    "properties": {
      "DayHeader": {
        "properties": {
          "Day": {
            "const": "SUNDAY"
          }
        }
      }
    }
  },
  {
    "properties": {
      "DayHeader": {
        "properties": {
          "Day": {
            "enum": [
              "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"
            ]
          }
        }
      },
      "ActivityDetail": {
        "properties": {
          "DayActivity": {
            "contains": {
              "required": ["StudyActivity"]
            }
          }
        }
      }
    }
  }
]

那么完整的架构可能看起来像这样:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["DayHeader", "ActivityDetail"],
  "properties": {
    "DayHeader": {
      "type": "object",
      "properties": {
        "Day": {
          "type": "string",
          "enum": [
            "SUNDAY",
            "MONDAY",
            "TUESDAY",
            "WEDNESDAY",
            "THURSDAY",
            "FRIDAY",
            "SATURDAY"
          ]
        }
      },
      "required": [
        "Day"
      ]
    },
    "ActivityDetail": {
      "type": "object",
      "required": ["DayActivity"],
      "properties": {
        "DayActivity": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "oneOf": [
              {
                "properties": {
                  "PhysicalActivity": {
                    "type": "string",
                    "enum": ["Walking", "Running"]
                  }
                },
                "required": ["PhysicalActivity"]
              },
              {
                "properties": {
                  "StudyActivity": {
                    "type": "string",
                    "enum": ["Maths Class", "Science Class"]
                  }
                },
                "required": ["StudyActivity"]
              },
              {
                "properties": {
                  "ArtActivity": {
                    "type": "string",
                    "enum": ["Drawing", "Dance"]
                  }
                },
                "required": ["ArtActivity"]
              }
            ]
          },
          "contains": {
            "required": ["PhysicalActivity"]
          }
        }
      }
    }
  },
  "oneOf": [
    {
      "properties": {
        "DayHeader": {
          "properties": {
            "Day": {
              "const": "SUNDAY"
            }
          }
        }
      }
    },
    {
      "properties": {
        "DayHeader": {
          "properties": {
            "Day": {
              "enum": [
                "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"
              ]
            }
          }
        },
        "ActivityDetail": {
          "properties": {
            "DayActivity": {
              "contains": {
                "required": ["StudyActivity"]
              }
            }
          }
        }
      }
    }
  ]
}

以上成功验证了以下条件:

{
  "DayHeader": { "Day": "SUNDAY"},
  "ActivityDetail": {
    "DayActivity": [
      { "PhysicalActivity": "Walking" }
    ]
  }
}

但不能避免以下情况(因为缺少"StudyActivity"

{
  "DayHeader": { "Day": "WEDNESDAY"},
  "ActivityDetail": {
    "DayActivity": [
      { "PhysicalActivity": "Walking" }
    ]
  }
}