plumatic / schema

Clojure(Script) library for declarative data description and validation
Other
2.4k stars 256 forks source link

`s/enum` doesn't preserve order #453

Open lasiltan opened 5 months ago

lasiltan commented 5 months ago

s/enum doesn't preserve the order of the elements provided. The order is lost at https://github.com/plumatic/schema/blob/master/src/cljc/schema/core.cljc#L295 when set is called.

This screws up ordering, for example, in swagger.

Replacing set with LinkedHashSet. would preserve order

w01fe commented 5 months ago

Open to a PR, thanks for the report!

Is there a x-platform equivalent of LinkedHashSet? If not, we could store the ordered list and the set separately potentially?

frenchy64 commented 4 months ago

I think attaching the original vs onto the defrecord with assoc should work for all platforms.

(macros/defrecord-schema EnumSchema [vs]
  Schema
  (explain [this] (or (::explain this)
                      ;; backwards compat for users of ->EnumSchema
                      (cons 'enum vs))))

(clojure.core/defn enum
  "A value that must be = to some element of vs."
  [& vs]
  (assoc (EnumSchema. (set vs))
         ::explain (cons 'enum vs)))

EDIT: hmm, well EnumSchema is a record so an assoc can bring one of those fields out of sync. Unclear if that's a problem.

frenchy64 commented 1 week ago

Well, we could just treat the ordering as a hint that we can discard if the actual entries differ.