Fork me on GitHub
#malli
<
2022-07-27
>
Martynas Maciulevičius05:07:53

Is there a way to represent this as a map?

{id: string?
 size1: my-schema1
 size2: my-schema1
 size3: my-schema1}
Where I know that id will be present all the time and size1 and others are dynamic. i.e. they can exist or they can have completely different names. I could use map-of for the second part but I would like to use map for the id part.

Martynas Maciulevičius08:07:07

Instead I hardcoded the keys. It was simpler than think and solve for truly any key 😄

pppaul10:07:52

yes, i posted an issue about something like this on malli's github

pppaul10:07:02

(let [{:keys [additionalProperties]} form
                                          req-fields                     (->> required (mapv keyword) (into #{}))
                                          all-fields                     (concat props req-fields)]
                                      (if-not additionalProperties
                                        (make-map props req-fields)
                                        [:and
                                         [:fn (fn [m]
                                                (->>
                                                  (apply dissoc m all-fields)
                                                  (m/validate (m/schema [:map-of 'string? 'string?]))))]
                                         (make-map props req-fields)]))

pppaul10:07:36

that's code i use to transform a json schema map to act something like what you described

pppaul10:07:48

[:and
 [:fn (fn [m]
        (->>
          (dissoc m :optional :required)
          (m/validate (m/schema [:map-of keyword? string?]))))]
 [:map
  [:required [:enum :a :b]]
  [:optional {:optional true} [:enum :a :b]]
  ]]
ends up making something like that

pppaul10:07:51

make-map (fn [props req-fields]
                   (apply vector :map
                     (->> props
                       (mapv (fn [[k v]]
                               (if (get req-fields k)
                                 [k v]
                                 [k {:optional true} v])))
                       (sort-by first))))

pppaul10:07:06

there is some discussing in malli about making :closed be a schema, supporting this idea with the work around that i posted, but it's not got a PR or anything, so work around is best. you can replace the :map-ofwith a schema for each key very easily with the code i provided