1. ホーム
  2. json

[解決済み] 1つのフィールドまたは別のフィールド、あるいは(他の2つのフィールドのうちの1つ)を要求し、それらのすべてを要求しないようにするにはどうすればよいですか?

2023-06-26 22:06:14

質問

JSONのスキーマで、JSONに以下のいずれかが含まれているかどうかを検証するのに苦労しています。

  • 1 つのフィールドのみ
  • 別のフィールドのみ
  • (他の2つのフィールドのうちの1つ)のみ

のみで、複数存在する場合はマッチしません。

私の場合、具体的には

  • copyAll
  • fileNames
  • matchesFiles または doesntMatchFiles

を検証したいが、それ以上のものがあるときは受け付けない。

今のところ、こんな感じです。

{
    "$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"]}}]}
    ]
} ;

これは私が望む以上にマッチします。私はこれが以下の全てにマッチすることを望んでいます。

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

が、一致しない。

{"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"}

私が見逃している何か明白なものがあるのでしょう - それが何であるかを知りたいです。

どのように解決するのですか?

問題は "not" のセマンティクスです。 "not required" は "inclusion forbidden" を意味するものではありません。それは、そのスキーマを検証するためにそれを追加する必要がないことを意味するだけです。

しかし、より簡単な方法で仕様を満たすために "oneOf" を使用することができます。それは、"これらのスキーマのうち1つだけが検証可能である"という意味であることを覚えておいてください。以下のスキーマは、あなたが解決しようとしているプロパティの切り替えを実現するものです。

{
    "$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"
                    ]
                }
            ]
        }
    ]
}