validation - Prismatic schema: removing unanticipated keys -
my api receiving json data client.
i use schema perform validation , coercion on data receive, 1 additional requirement: if there map key not described in schema, ignore , remove instead of failing validation (this because client may send me "garbage" properties along ones care about. want tolerant that.).
so in nutshell, perform "deep select-keys
" on input data using schema, before validation/coercion.
example of need:
(require '[schema.core :as sc]) (def myschema {:a sc/int :b {:c sc/str (sc/optional-key :d) sc/bool} :e [{:f sc/inst}]}) (sanitize-and-validate myschema {:a 2 :b {:c "hello" :$$garbage-key 32} :e [{:f #inst "2015-07-23t12:29:51.822-00:00" :garbage-key 42}] :_garbage-key1 "woot"}) => {:a 2 :b {:c "hello"} :e [{:f #inst "2015-07-23t12:29:51.822-00:00"}]}
i haven't yet found reliable way of doing this:
- i can't seem in custom transformation, because seems walker not give access keys.
- i haven't had luck trying walk schema hand, because it's hard differentiate map schemas , scalar schemas in generic way; difficult account possible shapes schema can have.
is there obvious way i'm not seeing?
thanks!
a third solution, credits abp: use schema.coerce/coercer matcher remove unknown keys maps.
(require '[schema.core :as s]) (require '[schema.coerce :as coerce]) (require '[schema.utils :as utils]) (defn filter-schema-keys [m schema-keys extra-keys-walker] (reduce-kv (fn [m k v] (if (or (contains? schema-keys k) (and extra-keys-walker (not (utils/error? (extra-keys-walker k))))) m (dissoc m k))) m m)) (defn map-filter-matcher [s] (when (or (instance? clojure.lang.persistentarraymap s) (instance? clojure.lang.persistenthashmap s)) (let [extra-keys-schema (#'s/find-extra-keys-schema s) extra-keys-walker (when extra-keys-schema (s/walker extra-keys-schema)) explicit-keys (some->> (dissoc s extra-keys-schema) keys (mapv s/explicit-schema-key) (into #{}))] (when (or extra-keys-walker (seq explicit-keys)) (fn [x] (if (map? x) (filter-schema-keys x explicit-keys extra-keys-walker) x))))))
this was described cleanest solution primary author of schema, not require change schema work. it's way go.
usage example:
(def data {:a 2 :b {:c "hello" :$$garbage-key 32} :e [{:f #inst "2015-07-23t12:29:51.822-00:00" :garbage-key 42}] :_garbage-key1 "woot"}) ((coerce/coercer myschema map-filter-matcher) data) ;=> {:a 2, :b {:c "hello"}, :e [{:f #inst "2015-07-23t12:29:51.822-00:00"}]}
Comments
Post a Comment