不久前我问过simple polymorphic schemas,答案一段时间都有效。
现在我要验证的地图有一个附加值,该值取决于另一个键的值。
该对象的一个人为的例子:
{: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
,但我不能允许模式“松散”,因为意外的键/值应该被视为无效。
我也不想更改正在验证的地图的结构,只是为了允许使用此库进行验证。
是否有一种理智的方法来实现对具有多个条件子模式的地图的严格验证?
答案 0 :(得分:6)
一个讽刺的答案是,这可能是您的数据模型不太理想的气味,您应该考虑将其重构为具有嵌套结构,如
{:type-info {:type :foo :foo-param :bar}
:method-info {:method :baz :baz-rate :max}}
一个(或许)更有帮助的答案是,除了编写自定义谓词以进行验证之外,我认为使用开箱即用的模式集并不容易。
如果不希望这样,我想你需要引入一种新的模式类型。幸运的是,这在用户代码(或第三方库)中很容易实现。不幸的是,我没有看到以简洁和正交的方式表示这两个概念(严格联合和条件映射结构)的简单方法(没有将它们组合成单个条件联合模式,或者具有条件感知的联合)。我相信有一种方法,但初看起来对我来说并不明显。