This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-16
Channels
- # aws-lambda (10)
- # beginners (52)
- # boot (42)
- # cider (2)
- # cljs-dev (8)
- # cljsjs (4)
- # cljsrn (10)
- # clojars (3)
- # clojure (48)
- # clojure-conj (4)
- # clojure-dev (19)
- # clojure-italy (7)
- # clojure-norway (4)
- # clojure-russia (44)
- # clojure-spec (70)
- # clojure-uk (34)
- # clojurescript (39)
- # cursive (35)
- # data-science (11)
- # datomic (7)
- # emacs (6)
- # fulcro (2)
- # hoplon (12)
- # jobs (1)
- # juxt (18)
- # lein-figwheel (2)
- # leiningen (4)
- # luminus (9)
- # off-topic (29)
- # om (46)
- # onyx (131)
- # other-languages (24)
- # parinfer (84)
- # pedestal (10)
- # portkey (45)
- # protorepl (1)
- # re-frame (15)
- # reagent (43)
- # ring-swagger (41)
- # schema (6)
- # shadow-cljs (293)
- # slack-help (2)
- # specter (42)
@ikitommi, I’m picking up on some of the stuff @psalaberria002 was pestering you with.
(def my-date-time-conforming
(st/type-conforming
(assoc conform/string-type-conforming
:date-time
(fn [_ value]
(DateTime. value)))))
(spec/def ::id int?)
(spec/def ::name string?)
(spec/def ::date (st/spec (partial instance? DateTime) {:type :date-time}))
(spec/def ::id-name-date (spec/keys :req-un [::id ::name ::date]))
(context "/spec-test" []
:coercion :spec
(GET "/foo" []
:return ::id-name-date
(ok {:id 1 :name "foo" :date (DateTime.)}))
(POST "/foo" []
:return ::id-name-date
:body [b ::id-name-date]
(ok (do (println b) b))))
The GET
request seems to work perfectly, whereas I get an exception on the POST, indicating that somewhere along the line, something doesn’t know how to convert a DateTime
to a string:
Caused by: com.fasterxml.jackson.core.JsonGenerationException: Cannot JSON encode object of class: class java.lang.Class: class org.joda.time.DateTime
The second problem is that swagger understands that I have a field that’s named “date” but it doesn’t understand what kind of field it is, so it presents it as an object:
So how do I inform swagger/compojure-api/spec-tools that anything with the type :date-time
should have an example value like "2017-10-16T11:59:04.180Z"
returns: No implementation of method: :spec of protocol: #'schema.core/Schema found for class: spec_tools.core.Spec
@slipset hi, compojure-api separates three different stages for coercion: request
, response
and string
. You need to add the conformer also to reponse
to make it work.
also, spec conforming is a one-way pipeline, see https://gist.github.com/ikitommi/8a97080357fd7de06882ba99f0df974c.
to get DateTime into a String, you should add a cheshire encoder. (or jsonista encoder if you use that).
I think we need something simpler for the two-way transformations. Good ideas welcome.
and you can explicitely say :coercion compojure.api.coercion.spec/SpecCoercion
. All multimethods can break in develop with wild use of tools-refresh.
it also works after I changed the whole thing from defroutes to defapi... is there any difference there?
defapi
mounts all the standard middleware, so you shoudn’t use defapi
(or api
) under a defapi
(or api
).
there is a sample routing app in https://github.com/metosin/c2
(defn str->date-time [_ value]
(try
(DateTime. value)
(catch Exception e
value)))
(def my-date-time-conforming
(st/type-conforming
(assoc conform/string-type-conforming
:date-time
str->date-time)))
(def custom-coercion
(-> compojure.api.coercion.spec/default-options
(assoc-in
[:body :formats "application/json"]
(st/type-conforming
(merge
conform/json-type-conforming
{:date-time str->date-time}
conform/strip-extra-keys-type-conforming)))
compojure.api.coercion.spec/create-coercion))
(spec/def ::id int?)
(spec/def ::name string?)
(spec/def ::date (st/spec (partial instance? DateTime) {:type :date-time
:json-schema/default "2017-10-12T05:04:57.585Z"}))
(spec/def ::id-name-date (spec/keys :req-un [::id ::name ::date]))
(context "/spec-test" []
:coercion custom-coercion
(GET "/foo" []
:return ::id-name-date
(ok {:id 1 :name "foo" :date (DateTime.)}))
(POST "/foo" []
:return ::id-name-date
:body [b ::id-name-date]
(ok (do (println b) b #_(assoc b :date "lol")))))
Only problem now is that if I pass an unparsable date, eg 2017-lol-01
either in the request or the response, Muuntaja/jackson becomes upset.
So it seems like str->date-time
needs to return some value (other than an exception) to indicate that it failed to parse the string.