Взаимоисключающие группы свойств

Предположим, у меня есть объект с четырьмя возможными свойствами: a, b, c, d. a и b могут появляться только вместе (т. е. a появляется тогда и только тогда, когда появляется b). Если появляются a и b, c не может появляться (то есть a/b и c исключают друг друга). Если a и b не появляются, может появиться c (но не обязательно). d может появляться в любой комбинации с a/b, c или отдельно. Никакие другие свойства, кроме a, b, c или d, не могут появиться вообще.

Как мне выразить это как jsonschema? Я подозреваю, что мог бы использовать некоторую комбинацию oneOf и required, но я не могу понять правильное заклинание.


person Ray    schedule 27.01.2015    source источник


Ответы (2)


Вы можете сформулировать свои ограничения следующим образом:

  • либо: оба "a" и "b" присутствуют, а "c" нет
  • или: нет ни "a", ни "b". ("c" может присутствовать или не присутствовать)

Сказать «ни один» во втором пункте немного многословно. Здесь мы выразили это с помощью allOf/not. (Примечание: здесь вы не можете объединить их в одно предложение required, потому что вам нужен отдельный not для каждого из них.)

{
    "oneOf": [
        {
            "required": ["a", "b"],
            "not": {"required": ["c"]}
        },
        {
            "allOf": [
                {
                    "not": {"required": ["a"]}
                },
                {
                    "not": {"required": ["b"]}
                }
            ]
        }
    ]
}

Альтернативная структура

Есть еще один способ сказать «ни то, ни другое», то есть снова использовать oneOf. Поскольку вы должны передать ровно одно предложение из oneOf, если одна из записей имеет значение {} (проходит все), то все остальные варианты запрещены.

Хотя он немного более лаконичен, возможно, он немного менее интуитивно понятен для чтения:

{
    "oneOf": [
        {
            "required": ["a", "b"],
            "not": {"required": ["c"]}
        },
        {
            "oneOf": [
                {},
                {"required": ["a"]},
                {"required": ["b"]}
            ]
        }
    ]
}
person cloudfeet    schedule 27.01.2015
comment
Это сработало. В итоге я использовал первый вариант. Часть того, что меня бросило, заключается в том, что я не понимал, что не требуется на самом деле означает не разрешено. Спасибо! - person Ray; 27.01.2015

Другой альтернативой является использование объявления зависимостей схемы:

   "dependencies": {
     "c": {
       "allOf": [
       { 
         "not": { "required": [ "a" ] }
       },
       { 
         "not": { "required": [ "b" ] }
       }
     ]
     }, 
     "a": {
       "allOf": [
       { 
         "not": { "required": [ "c" ] }
       },
       { 
         "required": [ "b" ]
       }
     ]
     },
     "b": {
       "allOf": [
       { 
         "not": { "required": [ "c" ] }
       },
       { 
         "required": [ "a" ]
       }
     ]
     }
   }
person JonasL    schedule 11.02.2015