【问题标题】:JSON Schema 'Required' validation set/removed by checkboxJSON Schema“必需”验证集/由复选框删除
【发布时间】:2019-03-18 12:06:22
【问题描述】:

我正在设计一个使用 JSON Schema 建模的 Web 应用程序。我正在尝试创建一个带有文本区域和复选框的页面。文字区是解释我为什么喜欢披萨。如果用户点击复选框,他们确认他们不喜欢披萨。除非选中该复选框,否则该文本框是“必需的”。该复选框实际上作为布尔值运行,但无法更改正在使用的组件(因为用户研究人员是这样说的)。目前,我正在使用 AJV 来验证我的架构,它配置为在属性为 required 但未输入/选择任何输入时抛出 errorMessages.required

不幸的是,我对 JSON 架构完全没有经验。以下是我目前试图验证这一点的尝试。这可以正确呈现,但不能按我的意愿工作 - 在我的开发环境中,它只会验证任何内容,但在 jsonschemavalidator.net 上,除非选中该复选框,否则它不会验证。如何实现我想要的功能?

{
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
additionalProperties: false,
propertyNames: {
    enum: [
        'q-why-i-love-pizza',
        'q-i-hate-pizza'
    ]
},
properties: {
    'q-why-i-love-pizza': {
        type: 'string',
        title: 'If you love pizza, tell us why',
        maxLength: 500,
        errorMessages: {
            required: "Please tell us why you love pizza, or select 'I hate pizza'"
        }
    },
    'q-i-hate-pizza': {
        type: 'array',
        maxItems: 1,
        uniqueItems: true,
        items: {
            anyOf: [
                {
                    title: 'I hate pizza',
                    const: 'hate'
                }
            ]
        },
        errorMessages: {
            required: "Please tell us why you love pizza, or select 'I hate pizza'"
        }
    }
},
allOf: [
    {
        $ref: '#/definitions/if-not-checked-then-q-why-i-love-pizza-is-required'
    }
],
definitions: {
    'if-not-checked-then-q-why-i-love-pizza-is-required': {
        if: {
            not: {
                properties: {
                    'q-i-hate-pizza': {
                        const: 'hate'
                    }
                }
            }
        },
        then: {
            required: ['q-why-i-love-pizza'],
            propertyNames: {
                enum: [
                    'q-i-hate-pizza',
                    'q-why-i-love-pizza'
                    ]
                }
            }
        }
    }
}

编辑:

我希望得到以下结果:

{
    'q-why-i-love-pizza' : '',
    'q-i-hate-pizza' : ['']
}

这应该验证失败,因为没有选择任何值。

{
    'q-why-i-love-pizza' : 'I love pizza because it's amazing',
    'q-i-hate-pizza' : ['']
}

这应该通过,因为用户已经输入了他们喜欢披萨的原因,因此不需要单击复选框。

{
    'q-why-i-love-pizza' : '',
    'q-i-hate-pizza' : ['hate']
}

这应该通过,因为虽然用户没有告诉我们他们为什么喜欢披萨,但他们已经选中了该框以表明他们讨厌披萨。

{
    'q-why-i-love-pizza' : 'I am a user, so decided to tell you I hate pizza too',
    'q-i-hate-pizza' : ['hate']
}

这也应该通过,因为我需要接受这样的可能性,即用户会在方框中打勾表示他们讨厌披萨,但无论如何都要继续告诉我。

解决方案

{
    type: "object",
    properties: {    
        'q-why-i-love-pizza': {
            type: 'string',
            title: 'If you love pizza, tell us why',
            maxLength: 500,
            errorMessages: {
            required: "Please tell us why you love pizza, or select 'I hate pizza'"
            }
        },
        'q-i-hate-pizza': {
            type: 'array',
            maxItems: 1,
            uniqueItems: true,
            items: {
                anyOf: [
                    {
                        title: 'I hate pizza',
                        const: 'hate'
                    }
                ]    
            },
            errorMessages: {
                required: "Please tell us why you love pizza, or select 'I hate pizza'"
            }
        }
    },
    allOf: [
        { $ref: "#/definitions/if-not-checked-then-q-offender-contact-description-is-required" }
    ],
    definitions: {
        "if-not-checked-then-q-offender-contact-description-is-required": {
            if: {
                not: {
                    required: ["q-i-hate-pizza"]
                }
            },
            then: {
                required: ["q-why-i-love-pizza"]
            }
        }
    }
}

【问题讨论】:

    标签: jsonschema json-schema-validator ajv


    【解决方案1】:

    我已经简化了您的架构,所以这可能并不完美,但这种通用方法应该可行。

    {
      "type": "object",
      "properties": {
        "q-why-i-love-pizza": { "type": "string", "maxLength": 500 },
        "q-i-hate-pizza": { "const": ["hate"] }
      },
      "allOf": [
        { "$ref": "#/definitions/if-hates-pizza-then-q-why-i-love-pizza-is-required" }
      ],
      "definitions": {
        "if-hates-pizza-then-q-why-i-love-pizza-is-required": {
          "if": { "not": { "required": ["q-i-hate-pizza"] } },
          "then": { "required": ["q-why-i-love-pizza"] }
        }
      }
    }
    

    【讨论】:

    • 谢谢。为了我的渲染器,我不得不恢复你对我的“属性”的更改,但你的 if/then 部分似乎已经成功了!非常感谢!
    【解决方案2】:

    您已经完成了大部分工作,但您错过了一些您可能没有预料到的事情。

    if-not-checked-then-q-why-i-love-pizza-is-required 的架构。 const 关键字仅适用于该属性,如果它存在的话。 您需要将required 约束添加到if 架构。

    显然这是猜测,因为您尚未提供 JSON 实例数据。

    【讨论】:

    • 如果这不能解决您的问题,请提供预期的通过和失败的 JSON 实例数据。
    • 谢谢,这改善了我的情况。但是,它仍然不完全正确。它现在只会验证是否选中了复选框并且用户在文本区域中输入了一个值。我已经编辑了我的问题以包含我想要通过和失败的内容
    • 好的,所以如果你在你的if 块中创建q-i-hate-pizza,那么除了第二个实例之外,所有的都按预期工作,它应该通过,但失败了。
    • 我认为使用oneOf 创建这个结构会更容易,根据你的问题,它实际上在语义上更接近你想要的。它也应该更容易理解。我今天不太可能有时间来创建这个,但我想说试试看你是否能弄清楚。以后或明天我可能有时间帮忙。
    猜你喜欢
    • 2020-02-05
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    相关资源
    最近更新 更多