-
Notifications
You must be signed in to change notification settings - Fork 216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Schema Applications can use MapEntry properties #212
Conversation
Tested if there is a quick fix for this using Idea was, that for contained schemas ( For example, one should check (defn- -json-schema-visitor [schema children _in options]
(let [p (m/properties schema)
pp (m/parent-properties schema)]
(or (unlift pp :json-schema)
(unlift p :json-schema)
(merge (select p)
(select pp)
(if (satisfies? JsonSchema schema)
(-accept schema children options)
(accept (m/type schema) schema children options))
(unlift-keys p :json-schema)
(unlift-keys pp :json-schema))))) => (json-schema/transform
[:and {:json-schema/title "and"}
int?
boolean?])
;{:allOf [{:type "integer", :format "int64", :title "and"}
; {:type "boolean", :title "and"}]
; :title "and"} Just adding the parent handling to Pushing the special code into JSON Schema (defmethod accept :map [_ _ children _]
(let [required (->> children (filter (comp not :optional second)) (mapv first))]
{:type "object"
:properties (apply array-map (mapcat (fn [[k p s]]
[k (or (unlift p :json-schema)
(merge (select p)
(unlift-keys p :json-schema)
s))]) children))
:required required})) and copy-paste (previously not neede code!) to swagger: (defmethod accept :map [_ _ children _]
(let [required (->> children (filter (comp not :optional second)) (mapv first))]
{:type "object"
:properties (apply array-map (mapcat (fn [[k p s]]
[k (or (json-schema/unlift p :swagger)
(json-schema/unlift p :json-schema)
(merge
(json-schema/select p)
(json-schema/unlift-keys p :json-schema)
(json-schema/unlift-keys p :swagger)
s))]) children))
:required required})) Based on the few hours spent on this, it looks like we should have first class (internal) (m/to-map-syntax
[:map
[:x int?]
[:y {:optional true} int?]]) would return instead of: 0) current:
{:type :map
:children [[:x nil {:type int?}]
[:y {:optional true} {:type int?}]]} 1) hybrid syntax:
{:type :map
:children [[:x {:type :malli.core/entry
:children [{:type int?}]}]
[:y {:type :malli.core/entry
:properties {:optional true}
:children [{:type int?}]}]]} 2) post-hybrid
{:type :map
:children [{:type :malli.core/entry
:children [:x {:type int?}]}
{:type :malli.core/entry
:properties {:optional true}
:children [:y {:type int?}]}]} 3) full type
{:type :map
:children [{:type :malli.core/entry
:properties {:malli.core/key :x}
:children [{:type int?}]}
{:type :malli.core/entry
:properties {:malli.core/key :y
:optional true}
:children [{:type int?}]}]} Hmm. |
Heureka! Conditional walking. |
All work but the error messages. |
c98e0e1
to
5aac446
Compare
challenge with errors is that errors are reported currently on the failing schema, for composite schemas like top-down would mean: (-> [:map
[:x {:error/message "from entry, over 18"}
[:and {:error/message "from and, over 18"}
int? [:> 18]]]
(m/explain {:x 12})
(me/humanize))
; {:x ["from entry, over 18"]} should it be always looked up? (-> [:map
[:x {:error/message "from entry, over 18"}
[:and {:error/message "from and, over 18"}
int? [:> {:error/message "from :>, over 18"} 18]]]
(m/explain {:x 12})
(me/humanize))
; {:x ["from entry, over 18"]} ... currently taken from the schema itself, if present. unlike everything else. |
Reletively happy with this now:
(def schema
[:map
[:x boolean?]
[:y {:optional true} int?]
[:z {:optional false} string?]])
(m/children schema)
;[[:x nil boolean?]
; [:y {:optional true} int?]
; [:z {:optional false} string?]]
(m/entries schema)
;[[:x [:malli.core/val boolean?]]
; [:y [:malli.core/val {:optional true} int?]]
; [:z [:malli.core/val {:optional false} string?]]
(every? map-entry? (m/entries schema))
; true
(map key (m/entries schema))
;(:x :y :z) still, does not throw: (m/entries int?)
; nil This would break everyone using (defn map-entries [s]
(if (m/entries s) (m/children s))) EDIT: IMO no, better to break this to keep things clean. |
* wrap :map and :multi child schemas in trnasformations * conditional walking with option :malli.core/walk-map-entries
@ikitommi Thanks for all your thought on this issue. Got a chance to play with the latest code and it's working great. Re. your question, I would break I think as we near release it will be worth adding doc-strings to both functions that explain when to use which one. My understanding (and please, correct me if I am wrong) is that most transformers would likely use Looked over the code as well - looks good! |
Thanks for the review! Will add the docstrings. |
some docs in 3443411 |
Spike on whether and how
MapEntry
properties should used in schema applications:error messages(postponed)Related issues: #80, #86, #116, #120, #182
Related PRs: #119, #197
forms
transformation
:encoders
&:decoders
?error messages
should use the parent props if definedvalue generation
json-schema
swagger