This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-18
Channels
- # announcements (31)
- # asami (11)
- # aws (33)
- # babashka (30)
- # beginners (69)
- # calva (1)
- # chlorine-clover (10)
- # cider (3)
- # clj-kondo (24)
- # cljdoc (19)
- # cljs-dev (1)
- # cljsrn (2)
- # clojure (104)
- # clojure-australia (4)
- # clojure-dev (29)
- # clojure-europe (202)
- # clojure-germany (36)
- # clojure-nl (6)
- # clojure-poland (3)
- # clojure-serbia (6)
- # clojure-spec (18)
- # clojure-uk (32)
- # clojurescript (36)
- # conjure (1)
- # core-async (6)
- # datomic (15)
- # duct (1)
- # emacs (11)
- # fulcro (24)
- # graalvm (12)
- # jobs (3)
- # juxt (1)
- # kaocha (2)
- # keechma (4)
- # lsp (1)
- # malli (102)
- # meander (17)
- # off-topic (16)
- # pathom (8)
- # re-frame (12)
- # remote-jobs (7)
- # rewrite-clj (72)
- # shadow-cljs (27)
- # sql (26)
- # tools-deps (8)
- # vim (3)
- # xtdb (28)
- # yada (5)
Hi, I'm just working through the Readme tutorial on the latest 0.3.0 and found that this example failed:
(m/validate
[:map
["status" [:enum "ok"]]
[1 any?]
[nil any?]
[::a string?]]
{"status" "ok"
1 'number
nil :yay
::a "properly awesome"})
; => true
Instead I get an exception:
1. Unhandled clojure.lang.ExceptionInfo
:malli.core/naked-keys-not-supported nil
{:type :malli.core/naked-keys-not-supported, :data nil}
Is this a regression or API change? I couldn't find references to "naked keys" apart from internal impl code
Is there a way to filter data by a schema? So if I have data of the form {:a 1 :b 2} and a schema of the form [:map [:a int?]] can I "apply" the schema to the data in order to get {:a 1}? All I can think of right now is to use m/explain then parse the errors.
@raymcdermott would this be ok:
(def Org-Ref
[:map {:title "Organisation name"}
[:ref {:swagger/description "Reference to the organisation"
:swagger/example "Acme floor polish, Houston TX"} :string]
[:kikka [:string {:swagger {:title "kukka"}}]]])
(defn remove-swagger-keys [p]
(not-empty (apply dissoc p (into #{:swagger} (->> p (keys) (filter (comp #{:swagger} keyword namespace)))))))
(defn walk-properties [schema f]
(m/walk
schema
(fn [s _ c _]
(m/into-schema
(m/-parent s)
(f (m/-properties s))
(cond->> c (m/entries s) (map (fn [[k p s]] [k (f p) (first (m/children s))])))
(m/options s)))
{::m/walk-entry-vals true}))
(walk-properties Org-Ref remove-swagger-keys)
;[:map {:title "Organisation name"}
; [:ref :string]
; [:kikka :string]]
e.g. walk the entrys, un-walk on the way back. apply f
on all properties (entrys & schemas)
@roseneck you can transform the value using strip-extra-keys-transformer
:
(m/decode [:map [:a int?]] {:a 1, :b 2} (mt/strip-extra-keys-transformer))
; => {:a 1}
@ikitommi perfect, thank you very much!
is it possible to introspect the malli schema from inside an :error/fn
fn ? i.e. i want to (first (m/children schema))
so i can print out the enum values in the error message
@robert-stuttaford sure, the fn takes the explain error map as argument, it has the :schema
key.
when i try this, i get m/children
isn't a thing, because it's SCI that's running this code
(thank you for your quick response)
Execution error (ExceptionInfo) at sci.impl.utils/throw-error-with-location (utils.cljc:51).
Could not resolve symbol: m/children
is there a trick to get it to see malli?
there is ::m/sci-options
to override the bindings. The default bindings are:
(defn -default-sci-options []
{:preset :termination-safe
:bindings {'m/properties properties
'm/type type
'm/children children
'm/entries entries}})
have the sci-options changed? don’t seem to work anymrethe options have not been changed, but :bindings
are only valid within the user
namespace, always have been. it's better to use explicit :namespaces
honestly i'm using sci because malli is
yes :termination-safe
has been removed for a while already, also documented in release notes
all i'm doing is writing malli specs at the repl with :error/fn and i ran into an error 'sci not available', so i put it on the CP and onward i went
@robert-stuttaford if you don’t need the seriaization thing, just pass a real function.
oh man. the fn is quoted. shit. sorry for the noise, fellas
that's what I thought :) maybe the error message should be : use sci for serialized schemas
all properties which have functions as values use the malli.eval
, which uses sci
as default for quoted code.
(defn -default-sci-options []
{:namespaces {'malli.core {'properties properties
'type type
'children children
'entries entries}}})
Execution error (ExceptionInfo) at sci.impl.utils/throw-error-with-location (utils.cljc:50).
Could not resolve symbol: malli.core/chidren [at line 1, column 10]
(defn evaluator [options fail!]
(let [eval-string* (dynaload/dynaload 'sci.core/eval-string* {:default nil})
init (dynaload/dynaload 'sci.core/init {:default nil})
fork (dynaload/dynaload 'sci.core/fork {:default nil})]
(fn [] (if (and @eval-string* @init @fork)
(let [ctx (init options)]
(fn eval [s] (eval-string* (fork ctx) (str s))))
fail!))))
like:
(defn evaluator [options fail!]
(let [eval-string* (dynaload/dynaload 'sci.core/eval-string* {:default nil})
init (dynaload/dynaload 'sci.core/init {:default nil})
fork (dynaload/dynaload 'sci.core/fork {:default nil})]
(fn [] (if (and @eval-string* @init @fork)
(let [ctx (init options)]
(eval-string* ctx "(alias 'm 'malli.core)")
(fn eval [s] (eval-string* (fork ctx) (str s))))
fail!))))
how do I transform the keys of a schema? e.g., I have [:map [:a-k string?] [:b-k string?]]
and I want to derive a schema that is the same but with snake-case keys: [:map [:a_k string?] [:b_k string?]]
@euccastro try m/walk
with m/schema-walker
check that the schema is a :map
and recreate the children.
is the best way to specify a literal value to use a single-item enum?
[:= value]
Tried to use this to build a core.match like this ;) https://gist.github.com/borkdude/26906ee15585ed5e1b7a8eda4cc1ee18
nice man
dumb question, how do you get a schema from the registry by its key
I was thinking (malli/-schema malli/default-registry ::sq/sqid)
but -schema
is private
[:map
[:field-a string?]
[:field-b [:one-of
[:map [:status [:= :not-asked]]]
[:map [:status [:= :loading]]]
[:map [:status [:= :failed]]]
[:map [:status [:= :success]
:value [:vector [:map [:id int?]]]]]]]
[:field-c [:one-of
[:map [:status [:= :not-asked]]]
[:map [:status [:= :loading]]]
[:map [:status [:= :failed]]]
[:map [:status [:= :success]
:value [:vector [:map [:id int?]]]]]]]
[:field-d [:set [:map [:id int?]]]]]
@danieleneal try (m/deref (m/schema ::sq/said))
might not be big difference, but performance. dispatch does one lookup to find the correct schema, :or
does linear scan over all.
I think last question for now - what would be the best way to reuse a structure like this
@ikitommi, (m/deref ::sq/sqid)
works thanks :thumbsup:
is there a way of getting the schema walker to deref while walking? I've got a schema which is like [:map [:some-key :some-schema] [:another-key :another-schema]]
where :some-schema
and :another-schema
are in the registry. I want to transform all the keys to snake case, but the schema walker doesn't descend into schema references.
@danieleneal see:
> e.g. ::m/walk-refs
& ::m/walk-schema-refs
& ::m/walk-entry-vals
.
walking respects those options, can't recall what does what. Please try, documentation PR welcome
oh cool
thanks again!!!
@emccue one way to reuse is to use local registry:
[:map {:registry {:user/success [:map
[:status [:= :success]]
[:value [:vector [:map [:id int?]]]]]
:user/default [:map
[:status [:enum :not-asked :loading :failed]]]
:user/field [:multi {:dispatch :status}
[:success :user/success]
[:malli.core/default :user/default]]}}
[:field-a string?]
[:field-b :user/field]
[:field-c :user/field]
[:field-d [:set [:map [:id int?]]]]]