问题
A little while ago I asked about simple polymorphic schemas, and the answer there worked well for a time.
Now the map I wish to validate has an additional value which is dependent upon another key's value.
A contrived example of the object:
{: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}
The discriminators here are :type
and :method
, each of which has its own set of valid sibling keys and values.
Previously only :type
existed, and the following worked:
(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
))
However now that there is more than one discriminator, the number of conditional branches would be combinatorial.
One option is to allow {s/Any s/Any}
in the maps and using s/both
, but I cannot allow the schemas to be 'loose', as unexpected key/values should be seen as invalid.
I also do not want to change the structure of the map being validated just to allow validation to work using this library.
Is there a sane way to achieve strict validation of maps that have multiple conditional sub-schemas?
回答1:
A snarky answer is that this may be a smell that your data model is less than ideal, and you should consider refactoring it to have nested structure like
{:type-info {:type :foo :foo-param :bar}
:method-info {:method :baz :baz-rate :max}}
A (perhaps) more helpful answer is that I don't think this is easy with the out-of-the-box set of schemas, besides just writing a custom predicate for validation.
If this isn't desirable, I guess you need to introduce a new schema type. Fortunately, this is easy to do in user code (or a third-party library). Unfortunately, I don't see an easy way to represent these two concepts (strict union and conditional map structure) in a crisp and orthogonal way (without combining them into a single conditional-union schema, or having union be conditional-aware). I believe there's a a way, but it's not obvious to me at first look.
来源:https://stackoverflow.com/questions/24383809/validating-multiple-polymorphic-values-using-prismatic-schema