如何在使用”anyOf”时改进JSON Schema验证结果

huangapple go评论47阅读模式
英文:

How to improve JSON Schema validation results when using "anyOf"

问题

以下是您要的翻译内容:

We want to validate an array of elements with a JSON Schema Validator (https://github.com/networknt/json-schema-validator if that makes any difference).

Unfortunately we get quite ambiguous error messages if the validation fails and I am wondering if there is a way to improve this.

To make it clearer, I have created a small sample:

Each element in the array has a property "pet_type" which we can be sure to be there all the time (yeah I know that is discussable, but for the sake of argument let's ignore that for now). Each element has then some other properties.
This is the json schema right now.
Envelope (Basically with an array of elements)

Cat (one of the elements in the array)

Dog:

And the Pet.json, which specifies that "pet_type" is required on each of the elements.

The problem I have is that the error messages get very long, because the element is validated against all of the constraints, without narrowing it down a bit.

Let's say the JSON to validate looks like this:

"pet_type" is set to "Cat", so for a human it is "clear" that it should only validate against the Cat JSON Schema and then show that "age" is missing.

What really happens is that there are 4 violations:

  • age is missing (from the Cat JSON Schema)

  • bark is missing (from the Dog JSON Schema)

  • pet_type is violating the "Dog" enum constraint (from the Dog JSON Schema)

  • pet_type is violating the "Dog" regex pattern (from the Dog JSON Schema)

Note: I have added the enum/regex pattern in an act of trying to change the behavior, but it did not work.

I understand from a technical standpoint why it behaves like it does, I just want to know if it is possible to tell the validator somehow to first narrow down the validation based on pet_type and then keep validating?

What I tried to get it working:

  • I have tried to set the pet_type to string with an enum "Cat" and "Dog" and added one of those values to the Cat/Dog JSON Schema respectively in an attempt to make it clear which event has which pet_type.

  • I have tried to remove the Pet.json Schema completely, but that did not change anything.

  • I have tried to use if/then, but somehow this gets rid of all validation errors:

My sample I tried to validate gives no errors anymore:

英文:

We want to validate an array of elements with a JSON Schema Validator (https://github.com/networknt/json-schema-validator if that makes any difference).

Unfortunately we get quite ambiguous error messages if the validation fails and I am wondering if there is a way to improve this.

To make it clearer, I have created a small sample:

Each element in the array has a property "pet_type" which we can be sure to be there all the time (yeah I know that is discussable, but for the sake of argument let's ignore that for now). Each element has then some other properties.
This is the json schema right now.
Envelope (Basically with an array of elements)

{
  "title": "Envelope",
  "type": "object",
  "properties": {
    "pets": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "$ref": "./Cat.json"
          },
          {
            "$ref": "./Dog.json"
          }
        ]
      }
    }
  }
}

Cat (one of the elements in the array)

{
  "title": "Cat",
  "allOf": [
    {
      "$ref": "Pet.json"
    },
    {
      "type": "object",
      "properties": {
        "hunts": {
          "type": "boolean"
        },
        "age": {
          "type": "integer"
        },
        "pet_type": {
          "type": "string",
          "enum": [
            "Cat"
          ],
          "pattern": "Cat"
        }
      },
      "required": [
        "pet_type",
        "age"
      ]
    }
  ]
}

Dog:

{
  "title": "Dog",
  "allOf": [
    {
      "$ref": "Pet.json"
    },
    {
      "type": "object",
      "properties": {
        "bark": {
          "type": "boolean"
        },
        "breed": {
          "type": "string"
        },
        "pet_type": {
          "type": "string",
          "enum": [
            "Dog"
          ],
          "pattern": "Dog"
        }
      },
      "required": [
        "bark"
      ]
    }
  ]
}

And the Pet.json, which specifies that "pet_type" is required on each of the elements.

{
  "title": "Pet",
  "type": "object",
  "discriminator": {
    "propertyName": "pet_type"
  },
  "properties": {
    "pet_type": {
      "type": "string",
      "enum": [
        "Cat",
        "Dog"
      ]
    }
  },
  "required": [
    "pet_type"
  ]
}

The problem I have is that the error messages get very long, because the element is validated against all of the constraints, without narrowing it down a bit.

Let's say the JSON to validate looks like this:

{
  "pets": [
    {
      "pet_type": "Cat",
      "hunts": true				
    }
  ]
}

"pet_type" is set to "Cat", so for a human it is "clear" that it should only validate against the Cat JSON Schema and then show that "age" is missing.

What really happens is that there are 4 violations:

  • age is missing (from the Cat JSON Schema)

  • bark is missing (from the Dog JSON Schema)

  • pet_type is violating the "Dog" enum contstraint (from the Dog JSON Schema)

  • pet_type is violating the "Dog" regex pattern (from the Dog JSON Schema)

Note: I have added the enum/regex pattern in an act of trying to change the behavior, but it did not work.

I understand from a technical standpoint why it behaves like it does, I just want to know if it is possible to tell the validator somehow to first narrow down the validation based on pet_type and then keep validating?

What I tried to get it working:

  • I have tried to set the pet_type to string with an enum "Cat" and "Dog" and added one of those values to the Cat/Dog JSON Schema respectively in an attempt to make it clear which event has which pet_type.

  • I have tried to remove the Pet.json Schema completely, but that did not change anything.

  • I have tried to use if/then, but somehow this gets rid of all validation errors:

{
  "title": "Envelope",
  "type": "object",
  "properties": {
    "pets": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "if": {
              "properties": {
                "pet_type": {
                  "const": "Cat"
                }
              }
            },
            "then": {
              "$ref": "./Cat.json"
            }
          },
          {
            "if": {
              "properties": {
                "pet_type": {
                  "const": "Dog"
                }
              }
            },
            "then": {
              "$ref": "./Dog.json"
            }
          }
        ]
      }
    }
  }
}

My sample I tried to validate gives no errors anymore:

{
  "pets": [
    {
      "pet_type": "Cat",
      "hunts": true				
    }
  ]
}

答案1

得分: 0

以下是已翻译的部分:

"Turns out the solution with if/then was correct, and the json-schema-validator actually detects the problems, but has some code that should improve the error messages, but gets rid of the validation errors instead.
I will bring the problem to their attention."

"原来使用 if/then 的解决方案是正确的,而 json-schema-validator 实际上会检测到问题,但它有一些代码应该改进错误消息,但却清除了验证错误。我将向他们提出这个问题。"

"For now I have found a workaround to use nested if/then/else statements:"

"目前,我已找到一种使用嵌套的 if/then/else 语句的解决方法:"

英文:

Turns out the solution with if/then was correct, and the json-schema-validator actually detects the problems, but has some code that should improve the error messages, but gets rid of the validation errors instead.
I will bring the problem to their attention.

For now I have found a workaround to use nested if/then/else statements:

{
	"title": "Envelope",
	"type": "object",
	"properties": {
		"pets": {
			"type": "array",
			"items": {
				"if": {
					"properties": {
						"pet_type": {
							"const": "Cat"
						}
					}
				},
				"then": {
					"$ref": "./Cat.json"
				},
				"else": {
					"if": {
						"properties": {
							"pet_type": {
								"const": "Dog"
							}
						}
					},
					"then": {
						"$ref": "./Dog.json"
					},
					"else": {
						"properties": {
							"pet_type": {
								"type": "string",
								"enum": [
									"Cat",
									"Dog"
								]
							}
						}
					}
				}
			}
		}
	},
	"additionalProperties": false
}

huangapple
  • 本文由 发表于 2023年2月6日 21:36:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75362005.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定