metosin / malli

High-performance data-driven data specification library for Clojure/Script.
Eclipse Public License 2.0
1.44k stars 205 forks source link

Add support for default/fallback branch for :map #871

Closed ikitommi closed 1 year ago

ikitommi commented 1 year ago

Resolution for #43

Bonuses:

TODO:

(def schema
  [:map
   [:id :int]
   ["age" :int]
   [::m/default [:map-of [:string {:decode/test str/upper-case}] :string]]])

(m/explicit-keys schema)
; => [:id "age"]

(m/default-schema schema)
; => [:map-of [:string {:decode/test str/upper-case}] :string]

(m/validate schema {:id 1, "age" 13, "kikka" "kukka"})
; => true

(m/decode
 schema
 {:id 1, "age" 13, "kikka" "kukka"}
 (mt/transformer
  (mt/string-transformer)
  (mt/transformer {:name :test})))
; => {:id 1, "age" 13, "KIKKA" "kukka"}

(m/explain schema {:id "1", "age" 13, "kikka" :kukka})
;{:schema ...,
; :value {:id "1", "age" 13, "kikka" :kukka},
; :errors ({:path [:id], :in [:id], :schema :int, :value "1"}
;          {:path [:malli.core/default 1], :in ["kikka"], :schema :string, :value :kukka})}

(m/parse schema {:id 1, "age" 13, "kikka" "kukka"})
;{:id 1, "age" 13, "kikka" "kukka"}

(mg/generate schema)
;{:id 12,
; "age" 4151222,
; "b9DR4P1s92" "1HV6XXcDqvqfF4NEMYL034as4",
; "5J4028PJp5n3z1BDX2h9zHwhT9" "CVeeNK72zQZ",
; "sRRhCH1" "2n2SGnKYY"}
(m/decode
 [:map
  [:x :int]
  [:y :int]
  [::m/default [:map-of :int :int]]]
 {:x 1, :y 2, :z 3, 1 1, "2" 2, 3 "3", "4" "4"}
 (mt/strip-extra-keys-transformer))
; => {:x 1, :y 2, 1 1}

(json-schema/transform
 [:map
  [:x :int]
  [::m/default [:map-of :int :int]]])
;{:type "object"
; :required [:x]
; :properties {:x {:type "integer"}}
; :additionalProperties {:type "integer"}}

(json-schema/transform
 [:map
  [:x :int]
  [::m/default [:map [:y :int]]]])
;{:type "object"
; :properties {:x {:type "integer"}
;              :y {:type "integer"}}
; :required [:x :y]}
cap10morgan commented 1 year ago

Looking good to me so far!

ikitommi commented 1 year ago

merge and union of two heterohomogenous maps needs to be figured too. Currently:

(mu/merge [:map-of :string :string] [:map-of :int :int])
; => [:map-of :int :int]

(mu/union [:map-of :string :string] [:map-of :int :int])
; => [:or [:map-of :string :string] [:map-of :int :int]]
ikitommi commented 1 year ago

Merging this, can tune the test later if needed, thanks for the review!