Hey,
This might be a silly question.
Is it possible to validate a map while ignoring optional fields if they are invalid?
for example it would return false
here:
(m/validate [:map
[:a string?]
[:b {:optional true} int?]]
{:a "Hey" :b "Nope"})
=> false
But there would be a way to conform a map with invalid optional fields and “sanitize” the map
; This made-up function would return {:a "Hey"}
(m/conform [:map
[:a string?]
[:b {:optional true} int?]]
{:a "Hey" :b "Nope"})
Do you mean the first should return true
?
Hm, shouldn't a validation with an open map that just containts the schema for :a do the trick? Or let b be any? Under what circumstances should b be an int?
@ikitommi That's something I'd like to be able to do too. Is there an idiomatic way to do that?
> Do you mean the first should return `true`?
Yes 🙂
> recursively remove all values in `:errors` `:in` path. the invalid paths are part of the explain result:
The :optional
data is missing from the :schema
field, how can I know which field is safe to remove and which field makes the map actually invalid?
My scenario is an API with some optional fields. If the client doesn’t send then -> no worries. If the client sent some invalid optional fields, in some cases I’d like to pass the request and not fail it. (Such cases may be that the client is a mobile device with a crappy sdk, which might report invalid data for optional fields)
Also - > Do you mean the first should return `true`? Not without some hints or options.
; This is correct
(m/validate [:map
[:a string?]
[:b {:optional true} int?]]
{:a "Hey" :b "Nope"})
=> false
; Additional options
(m/validate [:map
[:a string?]
[:b {:optional true} int?]]
{:a "Hey" :b "Nope"}
{:fail-on-optional? false)
=> true
ping @evg.tso
as the slack history rolls out fast, pasted the example into https://github.com/metosin/malli/blob/master/docs/tips.md#allowing-invalid-values-on-optional-keys
That’s great, thanks @ikitommi!
Is there a way to conform/remove the invalid optional fields?
yes. Many ways to do that :
1) attach a custom transformer to the new :any
fields to strip those away
2) in case of error, call m/explain
and remove all values from paths that have error
don't have time to write an example, but definitely doable 😉
The allow-invalid-optional-values
function is missing the (m/options s)
arg of mu/transform-entries
hi! I've been really impressed with malli
so far. really appreciate all the work you've put into it.
I'm trying to generate sample values from a schema, and I'm encountering a case where :orn
fails and :altn
succeeds:
(mg/generate [:altn [:bool boolean?] [:num int?]] {:seed 20})
=> [true]
(mg/generate [:orn [:bool boolean?] [:num int?]] {:seed 20})
=> Execution error (ExceptionInfo) at malli.impl.util/-fail! (util.cljc:16).
:malli.generator/no-generator {:schema [:orn [:bool boolean?] [:num int?]], :options {:seed 20}}
Is this expected at this stage? Is there additional implementation for :orn
generators that still needs to be done, or is this a bug?simple :or
also succeeds on this case:
(mg/generate [:or boolean? int?] {:seed 20})
=> true
What’s your opinion on something like:
(defn allow-invalid-optional-values [schema]
(m/walk
schema
(m/schema-walker
(fn [s]
(cond-> s
(m/entries s)
(mu/transform-entries
(partial map (fn [[k {:keys [optional] :as p} s]]
(if optional
[k
(assoc p :original-spec s
:decode/remove-invalid-fields {:compile (fn [schema _]
(fn [x]
(if-let [original-spec (:original-spec (m/properties schema))]
(when (m/validate original-spec x)
x)
x)))})
:any]
[k p s])))
(m/options s)))))))
(-> [:map
[:a string?]
[:b {:optional true} int?]]
allow-invalid-optional-values
(m/decode
{:a "Hey" :b "Nope"}
(mt/transformer {:name :remove-invalid-fields})))
=> {:a "Hey", :b nil}
I don’t like having multiple transformers, though.
How can I unify them? Similarly to what malli
offers with mt/strip-extra-keys-transformer
?https://github.com/metosin/malli/commit/da6366dd845b300923a5aec28eae96f15a8c9f71
merged in master
wow, that was fast! thanks!
it's weekend, the time where magic OSS happens
pushed out [metosin/malli "0.3.1"]
, finally with a working cljdoc - https://cljdoc.org/d/metosin/malli/0.3.1/doc/changelog.