web-dev-qa-db-fra.com

Comment dois-je exiger un champ ou un autre ou (l'un des deux autres) mais pas tous?

J'ai du mal à trouver un schéma JSON qui validera si le JSON contient:

  • un seul champ
  • un autre champ seulement
  • (l'un des deux autres champs) uniquement

mais pas pour correspondre lorsque plusieurs de ceux-ci sont présents.

Dans mon cas en particulier, je veux l'un des

  • copyAll
  • fileNames
  • matchesFiles et/ou doesntMatchFiles

pour valider mais je ne veux pas accepter quand il y en a plus.

Voici ce que j'ai jusqu'à présent:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "required": [ "unrelatedA" ],
    "properties": {
    "unrelatedA": {
        "type": "string"
    },
    "fileNames": {
        "type": "array"
    },
    "copyAll": {
        "type": "boolean"
    },
    "matchesFiles": {
        "type": "array"
    },
    "doesntMatchFiles": {
        "type": "array"
        }
    },
    "oneOf": [
         {"required": ["copyAll"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["fileNames"]}},
         {"required": ["fileNames"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["copyAll"]}},
         {"anyOf": [
               {"required": ["matchesFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}},
               {"required": ["doesntMatchFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}}]}
    ]
} ;

Cela correspond plus que je ne le souhaite. Je veux que cela corresponde à tous les éléments suivants:

{"copyAll": true, "unrelatedA":"xxx"}
{"fileNames": ["aab", "cab"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "unrelatedA":"xxx"}
{"doesntMatchFiles": ["a*"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "doesntMatchFiles": ["*b"], "unrelatedA":"xxx"}

mais pas pour correspondre:

{"copyAll": true, "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"copyAll": true, "doesntMatchFiles": ["*b"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"unrelatedA":"xxx"}

J'imagine qu'il manque quelque chose d'évident - j'aimerais savoir ce que c'est.

40
user3486184

Le problème est la sémantique "non". "non requis" ne signifie pas "inclusion interdite". Cela signifie simplement que vous n'avez pas besoin de l'ajouter pour valider ce schéma.

Cependant, vous pouvez utiliser "oneOf" pour satisfaire votre spécification d'une manière plus simple. N'oubliez pas que cela signifie que "un seul de ces schémas peut valider". Le schéma suivant réalise le changement de propriété que vous essayez de résoudre:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "required": [
        "unrelatedA"
    ],
    "properties": {
        "unrelatedA": {
            "type": "string"
        },
        "fileNames": {
            "type": "array"
        },
        "copyAll": {
            "type": "boolean"
        },
        "matchesFiles": {
            "type": "array"
        },
        "doesntMatchFiles": {
            "type": "array"
        }
    },
    "oneOf": [
        {
            "required": [
                "copyAll"
            ]
        },
        {
            "required": [
                "fileNames"
            ]
        },
        {
            "anyOf": [
                {
                    "required": [
                        "matchesFiles"
                    ]
                },
                {
                    "required": [
                        "doesntMatchFiles"
                    ]
                }
            ]
        }
    ]
}
83
jruizaranguren