This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-08-27
Channels
- # bangalore-clj (1)
- # beginners (187)
- # braveandtrue (52)
- # calva (7)
- # cider (17)
- # cljs-dev (14)
- # clojure (27)
- # clojure-austin (4)
- # clojure-dev (11)
- # clojure-finland (4)
- # clojure-italy (5)
- # clojure-nl (1)
- # clojure-russia (22)
- # clojure-spec (9)
- # clojure-uk (27)
- # clojurescript (91)
- # datomic (40)
- # duct (4)
- # emacs (14)
- # figwheel-main (36)
- # fulcro (11)
- # hoplon (10)
- # immutant (9)
- # instaparse (4)
- # java (1)
- # jobs (2)
- # off-topic (28)
- # pedestal (1)
- # reagent (15)
- # reitit (7)
- # remote-jobs (6)
- # ring-swagger (3)
- # shadow-cljs (28)
- # slack-help (1)
- # spacemacs (4)
- # specter (1)
- # sql (3)
- # testing (3)
- # tools-deps (24)
Hello, please forgive me as I'm a bit of a noob with swagger and spec but I'm having a little trouble with the swagger api with spec coercion.
Basically I have some maps where the fields have quite complicated specs and test generators, here is an example contract
map with a couple of specific decimal fields:
(defn non-negative? [n] (>= n 0))
(defn pos-scaled-decimal?
[scale]
(s/spec
(fn [x]
(and (non-negative? x) (decimal? x) (>= scale (.scale x))))
:gen #(gen/fmap (fn [x] (bigdec (/ (Math/abs x)
(Math/pow 10 (+ 1 (rand-int 6))))))
(gen/large-integer))))
(s/def ::pos-decimal-2dp (pos-scaled-decimal? 2))
(s/def ::urate1 ::pos-decimal-2dp)
(s/def ::urate2 ::pos-decimal-2dp)
(s/def ::contract (s/keys :req-un [::urate1 ::urate2]))
I would like to use generated maps as example input data on the swagger UI, on a vanilla swagger install to fill out the example post body with generated data I think that would look something like this:
:swagger {:paths {"/contract" {:post {:requestBody {:content {:application/json {:schema {:type "object" :example (gen/generate (s/gen ::contract))}}}}}}}
Is there a way to do this with reitit? I tried to use the ::contract
spec with parameter coercion:
["/contract"
{:post {:handler (fn [_]
{:status 200
:body "?"})
:parameters {:body ::contract}}}]
But example data on swagger ui gets turned into {:urate1 {}, :urate2 {}}
not (for example) {:urate1 0.01M, :urate2 0.07M}
Thanks@billh you can wrap the spec into spec-tools.core/Spec
, which can have extra metadata, including the :example
, something like:
(st/spec {:spec ::contract
:swagger/example (-> (s/exercise ::contract 1) first second)})
, should be picked up by the swagger transformeralso, both the coercion and the swagger transformer need to know the type of the leaf predicates to work properly. In your example the pos-scaled-decimal?
should return a spec-tools.core/Spec
too, instead of just functions / reified clojure.spec protocols.
something like this could work:
(defn pos-scaled-decimal?
[scale]
(st/spec
{:type :double
:spec (s/spec
(fn [x]
(and (non-negative? x) (decimal? x) (>= scale (.scale x))))
:gen #(gen/fmap (fn [x] (bigdec (/ (Math/abs x)
(Math/pow 10 (+ 1 (rand-int 6))))))
(gen/large-integer)))}))