使用Prismatic Sc​​hema验证多个多态值

Dre*_*kes 3 clojure plumatic-schema

不久之前,我问过简单的多态模式,答案一段时间内效果很好.

现在,我希望验证的地图有一个附加值,该值取决于另一个键的值.

一个人为的例子:

{: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}
Run Code Online (Sandbox Code Playgroud)

这里的鉴别符是: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
                 ))
Run Code Online (Sandbox Code Playgroud)

然而,现在有多个鉴别器,条件分支的数量将是组合的.

一种选择是允许{s/Any s/Any}在地图中使用s/both,但我不能允许模式"松散",因为意外的键/值应该被视为无效.

我也不想改变被验证的地图的结构,只是为了允许验证使用这个库工作.

是否有一种理智的方法来实现对具有多个条件子模式的映射的严格验证?

小智 6

一个讽刺的答案是,这可能是您的数据模型不太理想的气味,您应该考虑重构它以使嵌套结构像

{:type-info {:type :foo :foo-param :bar}
 :method-info {:method :baz :baz-rate :max}}
Run Code Online (Sandbox Code Playgroud)

一个(也许)更有帮助的答案是,除了编写自定义谓词以进行验证之外,我认为使用开箱即用的模式集并不容易.

如果这不合适,我猜你需要引入一种新的模式类型.幸运的是,这在用户代码(或第三方库)中很容易实现.不幸的是,我没有看到以简洁和正交的方式表示这两个概念(严格联合和条件映射结构)的简单方法(没有将它们组合成单个条件联合模式,或者具有条件感知的联合).我相信这是一种方式,但初看起来对我来说并不明显.