JSON模式-条件验证 [英] JSON Schema - conditional validation

查看:101
本文介绍了JSON模式-条件验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下架构.我已经尽力实现了它,但是它仍然没有按照我想要的那样工作.

I have the following Schema. I've implemented it as best I can, but it's still not working quite as I want it to.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "title": "Ordering pizza",
    "propertyNames": {
        "enum": [
            "q-who-did-you-order-from",
            "q-did-they-accept-your-order",
            "q-how-much-was-the-bill",
            "q-why-didnt-they-accept"
        ]
    },
    "properties": {
        "q-who-did-you-order-from": {
            "type": "string",
            "title": "Who have you ordered pizza from?",
            "maxLength": 50,
            "errorMessages": {
                "required": "Enter who you ordered from",
                "maxLength":
                    "Who you ordered from must be 50 characters or less"
            }
        },
        "q-did-they-accept-your-order": {
            "title": "Have they accepted your order?",
            "type": "boolean",
            "errorMessages": {
                "required":
                    "Select yes if they have accepted your order"
            }
        },
        "q-how-much-was-the-bill": {
            "type": "string",
            "title": "How much was the bill?",
            "maxLength": 50,
            "errorMessages": {
                "required": "Enter an amount",
                "maxLength": "Amount must be 50 characters or less"
            }
        },
        "q-why-didnt-they-accept": {
            "type": "string",
            "title": "Why wasnt your order accepted?",
            "description":
                "If you do not know you can say so.",
            "maxLength": 50,
            "errorMessages": {
                "required": "Enter a reason",
                "maxLength": "Reason must be 50 characters or less"
            }
        }
    },
    "required": ["q-who-did-you-order-from", "q-did-they-accept-your-order"],
    "allOf": [
        {
            "$ref": "#/definitions/if-false-then-q-why-didnt-they-accept-is-required"
        },
        {
            "$ref": "#/definitions/if-true-then-q-how-much-was-the-bill-is-required"
        }
    ],
    "definitions": {
        "if-false-then-q-why-didnt-they-accept-is-required": {
            "if": {
                "properties": {
                    "q-did-they-accept-your-order": {
                        "const": false
                    }
                }
            },
            "then": {
                "required": ["q-why-didnt-they-accept"],
                "propertyNames": {
                    "enum": [
                        "q-who-did-you-order-from",
                        "q-did-they-accept-your-order",
                        "q-why-didnt-they-accept"
                    ]
                }
            }
        },
        "if-true-then-q-how-much-was-the-bill-is-required": {
            "if": {
                "properties": {
                    "q-did-they-accept-your-order": {
                        "const": true
                    }
                }
            },
            "then": {
                "required": ["q-how-much-was-the-bill"],
                "propertyNames": {
                    "enum": [
                        "q-who-did-you-order-from",
                        "q-did-they-accept-your-order",
                        "q-how-much-was-the-bill"
                    ]
                }
            }
        }
    }
}

期望的是,用户将输入您订购的q"和您接受订购的q"的值,然后根据他们的答案仅输入其余两个问题中的一个对于q,他们接受您的订单了.

The expectation is that the user will enter a value for q-who-did-you-order-from and q-did-they-accept-your-order, then only one of the remaining two questions based on their answer for q-did-they-accept-your-order.

因此,以下输入应有效:

So the following inputs should validate:

{
    "q-did-you-order-from": "Pizza hut",
    "q-did-they-accept-your-order": "true",
    "q-how-much-was-the-bill": "20"
}



{
    "q-did-you-order-from": "Pizza hut",
    "q-did-they-accept-your-order": "false",
    "q-why-didn't-they-accept": "Incorrect card details"
}

类似地,我希望以下输入无法通过验证,并为包含空白字符串的字段抛出必需"错误.第一个应该抛出错误,因为q-为什么不接受它们为空:

Similarly, I would expect the following inputs to fail validation and throw a 'required' error for the field containing a blank string. The first should throw an error because q-why-didn't-they-accept is empty:

{
    "q-did-you-order-from": "Pizza hut",
    "q-did-they-accept-your-order": "false",
    "q-why-didn't-they-accept": ""
}

这个应该抛出一个错误,因为q-多少钱是空的.

And this one should throw an error because q-how-much-was-the-bill is empty.

{
    "q-did-you-order-from": "Pizza hut",
    "q-did-they-accept-your-order": "true",
    "q-how-much-was-the-bill": ""
}

做到了!这按预期工作.但是,我们发现了一个错误,该错误是由于用户未输入q-他们接受您的订单的答案而引起的.这些问题的答案在表单提交时通过浏览器发布.在浏览器中,布尔值问题显示为是/否单选按钮.结果,当用户不检查任何一个收音机,而是尝试提交表单时,将完全省略收音机的答案.发送的数据对象如下所示:

And it does! This works as expected. However, we found a bug that arises from the user not entering an answer to q-did-they-accept-your-order. The answers to these questions are POSTed via the browser on form submission. In the browser, the boolean question is presented as yes/no radio buttons. As a result, when the user does not check either radio, but does try to submit the form, the answer for the radios is omitted entirely. The data object sent looks like this:

{
    "q-did-you-order-from": "Pizza hut",
    "q-how-much-was-the-bill": "",
    "q-why-didn't-they-accept": "",
}

我在这里的预期结果:

AJV仅对q接受您的订单抛出一个必需"错误.它不应该对其他任何东西抛出必需"错误,因为不需要q多少票据和为什么不接受q,除非q的相关值是-他们接受您的订单.

AJV throws only one 'required' error for q-did-they-accept-your-order. It shouldn't throw a 'required' error for anything else as both q-how-much-was-the-bill and q-why-didn't-they-accept aren't required unless the related value for q-did-they-accept-your-order is selected.

我的实际结果:

AJV对所有三个空输入都引发错误.

AJV Throws an error for all three empty inputs.

所以我的问题是,如何使AJV验证此模式,并且在问题没有得到回答时,仅q-did-他们接受您的订单就会引发所需的错误.

So my question is, how do I get AJV to validate this schema and for ONLY q-did-they-accept-your-order to throw a required error when the question is not answered.

AJV的输出如下:

[
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/required",
        "params": {
            "missingProperty": "q-did-they-accept-your-order"
        },
        "message": "should have required property 'q-did-they-accept-your-order'"
    },
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/definitions/if-false-then-q-why-didnt-they-accept-is-required",
        "params": {
            "missingProperty": "q-why-didnt-they-accept"
        },
        "message": "should have required property 'q-why-didnt-they-accept'"
    },
    {
        "keyword": "if",
        "dataPath": "",
        "schemaPath": "#/definitions/if-false-then-q-why-didnt-they-accept-is-required/if",
        "params": {
            "failingKeyword": "then"
        },
        "message": "should match \"then\" schema"
    },
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/definitions/if-true-then-q-how-much-was-the-bill-is-required/then/required",
        "params": {
            "missingProperty": "q-how-much-was-the-bill"
        },
        "message": "should have required property 'q-how-much-was-the-bill'"
    },
    {
        "keyword": "if",
        "dataPath": "",
        "schemaPath": "#/definitions/if-true-then-q-how-much-was-the-bill-is-required/if",
        "params": {
            "failingKeyword": "then"
        },
        "message": "should match \"then\" schema"
    }
]

推荐答案

在您的if/then模式应用程序中缺少一部分.让我们以这个简单的模式为例.

There's a part missing from your application of the if/then pattern. Let's use this simple schema as an example.

{
  "if": {
    "properties": {
      "foo": { "const": true }
    }
  },
  "then": {
    "required": ["bar"]
  }
}

如果我针对此架构验证{},则将失败,要求提供属性"bar".因为/if模式不需要"foo"属性,所以{}是有效的,因此/then模式适用.要解决此问题,您只需要使"foo"属性成为必需.

If I validate {} against this schema, it will fail saying that the property "bar" is required. Because the /if schema doesn't require the "foo" property, {} is valid and therefore the /then schema applies. To fix this problem, you just need to make the "foo" property required.

{
  "if": {
    "properties": {
      "foo": { "const": true }
    },
    "required": ["foo"]
  },
  "then": {
    "required": ["bar"]
  }
}

现在,{}对架构有效. /then模式仅在存在"foo"属性且其值为true时适用.

Now, {} is valid against the schema. the /then schema will only apply if there is a "foo" property and it's value is true.

这篇关于JSON模式-条件验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆