首页 > 解决方案 > 根据为属性指定的值验证 Json 架构

问题描述

我有一个 Json 请求,其中包含以下数据和相应的 json 模式

有了这个请求,我想根据模式制作一些需要的字段

假设如果模式为 1,那么我希望 obj1 中的字段 a 和 b 是必需的,并且 obj3 中的字段 x 是必需的。现在,如果模式为 2,我希望 obj2 中的字段 p、q 和 r 是必需的,obj1 中的字段 a 和 c 是必需的,obj3 中的字段 y 是必需的。接下来如果模式是3,我只需要字段a和c

json请求

{
  "mode": "1",
  "obj1": {
      "a": 12,
      "b": "test",
      "c": "18 June 2019"
      },
 "obj2": {
      "p": 100,
      "q": "new",
      "r": "19 June 2019",
      "s" : "test2"
      },
  "obj3": {
      "x": 12,
      "y": "test3"
      }
}


**Json schema**
{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "properties": {
    "mode": {
      "$id": "#/properties/mode",
      "type": "string",
      "examples": [
        "1"
      ]
    },
    "obj1": {
      "$id": "#/properties/obj1",
      "type": "object",
      "title": "The Obj 1 Schema",
      "properties": {
        "a": {
          "$id": "#/properties/obj1/properties/a",
          "type": "integer",
          "examples": [
            12
          ]
        },
        "b": {
          "$id": "#/properties/obj1/properties/b",
          "type": "string",
          "examples": [
            "test"
          ]
        },
        "c": {
          "$id": "#/properties/obj1/properties/c",
          "type": "string",
          "examples": [
            "18 June 2019"
          ]
        }
      }
    },
    "obj 2": {
      "$id": "#/properties/obj2",
      "type": "object",
      "title": "The Obj 2 Schema",
      "properties": {
        "p": {
          "$id": "#/properties/obj2/properties/p",
          "type": "integer",
          "examples": [
            100
          ]
        },
        "q": {
          "$id": "#/properties/obj2/properties/q",
          "type": "string",
          "examples": [
            "new"
          ]
        },
        "r": {
          "$id": "#/properties/obj2/properties/r",
          "type": "string",
          "examples": [
            "19 June 2019"
          ]
        },
        "s": {
          "$id": "#/properties/obj2/properties/s",
          "type": "string",
          "examples": [
            "test2"
          ]
        }
      }
    },
    "obj 3": {
      "$id": "#/properties/obj3",
      "type": "object",
      "title": "The Obj 3 Schema",
      "properties": {
        "x": {
          "$id": "#/properties/obj3/properties/x",
          "type": "integer",
          "examples": [
            12
          ]
        },
        "y": {
          "$id": "#/properties/obj3/properties/y",
          "type": "string",
          "examples": [
            "test3"
          ]
        }
      }
    }
  }
}

编辑 - 根据@gregsdennis 的建议更改架构以进行验证

JSON 架构

    {
      "definitions": {},
      "$schema": "http://json-schema.org/draft-07/schema#",
      "$id": "http://example.com/root.json",
      "type": "object",
      "properties": {
        "mode": {
          "$id": "#/properties/mode",
          "type": "string",
          "examples": [
            "1"
          ]
        },
        "obj1": {
          "$id": "#/properties/obj1",
          "type": "object",
          "title": "The Obj 1 Schema",
          "properties": {
            "a": {
              "type": "integer",
              "examples": [
                12
              ]
            },
            "b": {
              "type": "string",
              "examples": [
                "test"
              ]
            },
            "c": {
              "type": "string",
              "examples": [
                "18 June 2019"
              ]
            }
          }
        },
        "obj 2": {
          "$id": "#/properties/obj2",
          "type": "object",
          "title": "The Obj 2 Schema",
          "properties": {
            "p": {
              "type": "integer",
              "examples": [
                100
              ]
            },
            "q": {
              "type": "string",
              "examples": [
                "new"
              ]
            },
            "r": {
              "type": "string",
              "examples": [
                "19 June 2019"
              ]
            },
            "s": {
              "type": "string",
              "examples": [
                "test2"
              ]
            }
          }
        },
        "obj 3": {
          "$id": "#/properties/obj3",
          "type": "object",
          "title": "The Obj 3 Schema",
          "properties": {
            "x": {
              "type": "integer",
              "examples": [
                12
              ]
            },
            "y": {
              "type": "string",
              "examples": [
                "test3"
              ]
            }
          }
        }
      },
"oneOf": [
    {
      "properties": {
        "mode": {"const": 1},
        "obj1": {"required": ["a","b"]},
        "obj3": {"required": ["x"]}
       }
    },
    {
      "properties": {
        "mode": {"const": 2},
        "obj2": {"required": ["p","q","r"]},
        "obj1": {"required": ["a","c"]},
        "obj3": {"required": ["y"]}
       }
    }
]
    }

因此,简而言之,无论我有多少模式、字段或对象,我都希望在给定时间为特定模式只需要来自不同对象的几个选定字段。任何人都可以提出任何解决方案来实现这一目标吗?是否可以在 json 模式中进行此类验证?

标签: jsonjsonschemajson-schema-validator

解决方案


您想要的是oneOf每个子模式为每个obj*属性提供有效状态的位置。每个状态都是这样的:

{
  "properties": {
    "mode": {"const": 1},
    "obj1": {"required": ["a","b"]},
    "obj3": {"required": ["x"]}
  }
}

为您在问题中列出的每个状态创建其中一个,并将它们全部放入oneOf根中。

可以if使用/ then/来执行此操作else,但对于这种情况,我希望oneOf避免嵌套。


另外,我注意到$id中间有很多多余的 s 只是指定它们在模式中的位置。你想要一个根,但你不需要其他的。实现可以轻松地计算出这些类型的基于位置的引用。


推荐阅读