代码之家  ›  专栏  ›  技术社区  ›  user6165050

Json-使用Python递归验证模式

  •  2
  • user6165050  · 技术社区  · 9 年前

    我试图使用 jsonschema Python 3中的模块。

    自定义JSON如下所示:

    {
      "endpoint": "rfc",
      "filter_by": ["change_ref", "change_i"],
      "expression": [
        {
          "field": "first_name",
          "operator": "EQ",
          "value": "O'Neil"
        },
        "AND",
        [
          {
            "field": "last_name",
            "operator": "NEQ",
            "value": "Smith"
          },
          "OR",
          {
            "field": "middle_name",
            "operator": "EQ",
            "value": "Sam"
          }
        ]
      ],
      "limit_results_to": "2"
    } 
    

    AND s和 OR

    我试图验证此模式的模板位于以下代码段中:

    import json
    import jsonschema
    
    
    def get_data(file):
        with open(file) as data_file:
            return json.load(data_file)
    
    
    def json_schema_is_valid():
        data = get_data("other.json")
        valid_schema = {
            "type": "object",
            "required": ["endpoint", "filter_by", "expression", "limit_results_to"],
            "properties": {
                "endpoint": {
                    "type": "string",
                    "additionalProperties": False
                },
                "filter_by": {
                    "type": ["string", "array"],
                    "additionalProperties": False
                },
                "limit_results_to": {
                    "type": "string",
                    "additionalProperties": False
                },
                "expression": {
                    "type": "array",
                    "properties": {
                        "field": {
                            "type": "string",
                            "additionalProperties": False
                        },
                        "operator": {
                            "type": "string",
                            "additionalProperties": False
                        },
                        "value": {
                            "type": "string",
                            "additionalProperties": False
                        }
                    },
                    "required": ["field", "operator", "value"]
                }
            }
        }
        return jsonschema.validate(data, valid_schema)
    
    
    if __name__ == '__main__':
        print(json_schema_is_valid())
    

    现在,似乎有些问题,因为当我运行上述代码时,我得到了 None 这可能(不)是好的。当我试图修改 type property Here ,似乎未分析表达式属性。更多,我阅读 here 我可以使用我的模板递归验证我的自定义JSON模式 '$ref': '#' 但我不太懂怎么用它。有人能给我一些提示吗?

    1 回复  |  直到 9 年前
        1
  •  0
  •   Peilonrayz    9 年前

    除了递归部分外,您的模式看起来正常工作。查看GitHub上的源代码 jsonschema.validate ,我们可以看到代码没有 return . 因此,我认为可以安全地假设您验证的方式是使用以下内容:

    try:
        jsonschema.validate(json_data, schema)
    except ...:
        print('invalid json')
    else:
        print('valid json')
    

    为了创建递归,您应该做两个定义。我在网上找到了这个方法 Recursive JSON Schema

    {
        "definitions": {
            "comparison": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                    "field": {
                        "type": "string"
                    },
                    "operator": {
                        "type": "string"
                    },
                    "value": {
                        "type": "string"
                    }
                },
                "required": ["field", "operator", "value"]
            }
        }
    }
    

    执行递归布尔比较有点困难。我不知道如何将数组限制为三个项,其中第二个是不同的类型,所以我选择使用一个对象,它有三个定义良好的项。此外,第一个和最后一个项目应该具有相同的类型,以便您可以像这样进行比较 (a and b) or (c and d) . 我得到了以下模式:

    {
        "definitions": {
            "comparison": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                    "field": {
                        "type": "string"
                    },
                    "operator": {
                        "type": "string"
                    },
                    "value": {
                        "type": "string"
                    }
                },
                "required": ["field", "operator", "value"]
            },
            "booleanComparison": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                    "item1": {
                        "type": "object",
                        "oneOf": [
                            {"$ref": "#/definitions/comparison"},
                            {"$ref": "#/definitions/booleanComparison"}
                        ]
                    },
                    "operator": {
                        "type": "string"
                    },
                    "item2": {
                        "type": "object",
                        "oneOf": [
                            {"$ref": "#/definitions/comparison"},
                            {"$ref": "#/definitions/booleanComparison"}
                        ]
                    }
                },
                "required": ["item1", "operator", "item2"]
            }
        },
        "type": "object",
        "properties": {
            "endpoint": {
                "type": "string"
            },
            "filter_by": {
                "type": ["string", "array"]
            },
            "limit_results_to": {
                "type": "string",
                "additionalProperties": false
            },
            "expression": {
                "type": "object",
                "oneOf": [
                    {"$ref": "#/definitions/comparison"},
                    {"$ref": "#/definitions/booleanComparison"}
                ]
            }
        },
        "required": ["endpoint", "filter_by", "expression", "limit_results_to"]
    }
    

    {
        "endpoint": "rfc",
        "filter_by": ["change_ref", "change_i"],
        "limit_results_to": "2",
        "expression": {
            "item1": {
                "field": "first_name",
                "operator": "EQ",
                "value": "O'Neil"
            },
            "operator": "AND",
            "item2": {
                "item1": {
                    "field": "last_name",
                    "operator": "NEQ",
                    "value": "Smith"
                },
                "operator": "OR",
                "item2": {
                    "field": "middle_name",
                    "operator": "EQ",
                    "value": "Sam"
                }
            }
        }
    }
    

    但是说如果你改变它是无效的 "value": "Sam" 到 "value": true