Hi. Trying to work with declarative :merge along with mutual recursion with :ref but failing either with invalid-ref or invalid-schema
(def ping-pong-registry
{::ping [:maybe [:merge
[:map
[:value [:= "ping"]]
[:person string?]]
[:map
[:child [:ref ::pong]]]]]
::pong [:maybe [:merge
[:map
[:value [:= "pong"]]
[:bot string?]]
[:map
[:child [:ref ::ping]]]]]})
(def ping-pong-schema
(m/schema [:schema {:registry ping-pong-registry} ::ping])) ; :malli.core/invalid-schema
(m/validate ping-pong-schema
{:value "ping"
:person "Jane"
:child {:value "pong"
:bot "c-3po"
:child {:value "ping"
:person "Jane"
:child {:value "pong"
:bot "c-3po"
:child {:value "ping"
:person "Jane"
:child nil}}}}})❤️
if you get the :malli.core/invalid-schema from repl you can print *e to see what is wrong there
here, its’:
{:cause ":malli.core/invalid-schema",
:data {:type :malli.core/invalid-schema,
:message :malli.core/invalid-schema,
:data {:schema :merge, ...
so, you don’t have :merge available.it’s not part of the default registry
I would:
(ns user
(:require [malli.core :as m]
[malli.generator :as mg]
[malli.registry :as mr]
[malli.util :as mu]))
;; change the default (global) registry
(mr/set-default-registry!
(mr/composite-registry
(m/default-schemas) ;; defaults
(mu/schemas))) ;; utility schemas like :merge
(def ping-pong-registry
{::ping [:maybe [:merge
[:map
[:value [:= "ping"]]
[:person string?]]
[:map
[:child [:ref ::pong]]]]]
::pong [:maybe [:merge
[:map
[:value [:= "pong"]]
[:bot string?]]
[:map
[:child [:ref ::ping]]]]]})
(def ping-pong-schema
(m/schema [:schema {:registry ping-pong-registry} ::ping]))
(mg/sample ping-pong-schema)
;(nil
; nil
; nil
; nil
; {:value "ping", :person "", :child nil}
; {:value "ping", :person "4", :child nil}
; {:value "ping", :person "", :child nil}
; {:value "ping", :person "fwYAz", :child {:value "pong", :bot "", :child nil}}
; {:value "ping", :person "Yk", :child nil}
; {:value "ping", :person "ne3ICu", :child nil})Worth noting that that these features have known issues in combination https://github.com/metosin/malli/issues/1088
Clojurists Together is funding Malli this quarter. I will be enhancing the base schemas with constraints that can express fine-grained specs like "map where :user and :pass only occur together" or "non-blank strings", all the way to "a password must contain numbers, letters, and symbols". The system will be extensible, and be fully compatible with validation/explanation/generation/parsing etc. Humanization will be enhanced for automatically improved error messages:
(def Password
[:string {:min 5
:and [[:not [:non-alpha]]
[:not [:non-numeric]]
(into [:or] (map #(do [:includes (str %)]))
[\; \! \@ \# \$ \% \^ \& \*])]}])
(me/humanize (m/explain Password ""))
;=> [[:and
"should contain an alphabetic character"
"should contain a numeric character"
[:or
"should include substring \";\""
"should include substring \"!\""
"should include substring \"@\""
"should include substring \"#\""
"should include substring \"$\""
"should include substring \"%\""
"should include substring \"^\""
"should include substring \"&\""
"should include substring \"*\""]
"should be at least 5 characters, given 0"]]
I will be giving a talk on Thursday to help plan my quarter and gather feedback. I tried to choose a time overlapping with many American and European timezones. A recording will be posted after.
https://www.youtube.com/live/28S96Ms8WOc
https://time.is/1200PM_29_Aug_2024_in_CThttps://time.is/1200PM_29_Aug_2024_in_CT@ben.sless agreed it's quite powerful to make them properties
I was dissuaded from naming that property :charset because it was too overloaded, but an alternative could be :format with the value a keyword or a coll of keywords / preds
alternative is to just let every one of those preds be a property. why? you can specify :alpha true :excludes #{"v" "c"}
In a sense, a map, being an aggregate, already has :and semantics
yes, an existing example is {:min 1 :max 2}
precisely
however, translating the Password example, the result seems nonsensical
(def Password
[:string {:min 5
:alpha true
:numeric true
:includes [\; \! \@ \# \$ \% \^ \& \*]}])
right that's why there's connectives, but the top level is always a conjunction
This should probably be :printable
looking at all the is* predicates for java.lang.Character
Another to consider is simply format, e.g. JSON Schema email
String contents? That takes me back https://github.com/metosin/malli/pull/587
In case I don't make it to the meeting, I firmly believe these should all be string properties and not schemas