Проверка нескольких полиморфных значений с использованием призматической схемы

Некоторое время назад я спросил о простых полиморфных схемах, и какое-то время ответ работал хорошо.

Теперь карта, которую я хочу проверить, имеет дополнительное значение, которое зависит от значения другого ключа.

Надуманный пример объекта:

{:type      :foo         {:type      :bert        {:type      :foo
 :foo-param :bar          :bert-size :medium       :foo-param :bar
 :method    :baz          :method    :baz          :method    :bang
 :baz-rate  :max}         :baz-rate  :max}         :bangness  :considerable}

Дискриминаторами здесь являются :type и :method, каждый из которых имеет собственный набор допустимых одноуровневых ключей и значений.

Раньше существовало только :type, и работало следующее:

(def ^:private test-base-schema {:type (s/enum :foo :abc :banana)})

(def test-schema
  (s/conditional #(= (:type %) :foo)
                 (merge test-base-schema {:foo-param s/Keyword})
                 ; other conditions here
                 ))

Однако теперь, когда имеется более одного дискриминатора, количество условных ветвей будет комбинаторным.

Один из вариантов — разрешить {s/Any s/Any} на картах и ​​использовать s/both, но я не могу допустить, чтобы схемы были «свободными», так как неожиданные ключи/значения должны рассматриваться как недействительные.

Я также не хочу менять структуру проверяемой карты только для того, чтобы проверка работала с использованием этой библиотеки.

Есть ли разумный способ добиться строгой проверки карт, которые имеют несколько условных подсхем?


person Drew Noakes    schedule 24.06.2014    source источник


Ответы (1)


Язвительный ответ заключается в том, что это может быть запахом того, что ваша модель данных не идеальна, и вам следует подумать о ее рефакторинге, чтобы иметь вложенную структуру, например

{:type-info {:type :foo :foo-param :bar}
 :method-info {:method :baz :baz-rate :max}}

(Возможно) более полезный ответ заключается в том, что я не думаю, что это легко с готовым набором схем, помимо простого написания собственного предиката для проверки.

Если это нежелательно, я думаю, вам нужно ввести новый тип схемы. К счастью, это легко сделать в пользовательском коде (или в сторонней библиотеке). К сожалению, я не вижу простого способа представить эти две концепции (строгое объединение и структуру условной карты) в четкой и ортогональной форме (без объединения их в единую схему условного объединения или без учета условий объединения). Я верю, что есть способ, но он не очевиден для меня на первый взгляд.

person Jason Wolfe    schedule 24.06.2014