Hi, how do you guys apply spec for dates? specifically with clj-time if possible?
I’m using compojure-api
I want to coerce strings to clj-time dates
Dates in general is a can of worms. 🙂 My current attempt is to use strictly ISO 8601 formatted strings when transferring dates over wire. I use regexp to validate the strings at the edges using spec
and I do coercion to date instances in business logic if/when needed.
Time will show how much pain this approach causes.
doesn’t inst?
predicate just work?
(st/encode inst? (java.util.Date.) st/json-transformer)
; "2019-01-11T13:46:36.469+0000"
(st/decode inst? "2019-01-11T13:46:36.469+0000" st/json-transformer)
; #inst"2019-01-11T13:46:36.469-00:00"
I guess clj-time (joda) would require custom Specs to work. But that should be relatively straightforward to do?
It works but I’d like to convert to clj-time, the spec itself is ok but I can’t make it nice in swagger
ended up using something like https://github.com/metosin/compojure-api/blob/master/test19/compojure/api/coercion/spec_coercion_test.clj
tks all
what does nice in swagger mean?
btw, you can attach the encode & decode functions to specs too:
(s/def ::date
(st/spec
{:spec (partial instance? DateTime)
:type :date-time
:reason "FAIL"
:encode/json str->date-time
:json-schema/default "2017-10-12T05:04:57.585Z"}))
also add swagger hints, like:
(s/def ::date
(st/spec
{:spec (partial instance? DateTime)
:type :date-time
:reason "FAIL"
:encode/json str->date-time
:swagger/type "date-time"
:json-schema/default "2017-10-12T05:04:57.585Z"}))
oh thats pretty cool
nice means the example value gets generated correctly
e.g. encode
and decode
namespaces control how the spec gets transformed, json-schema
and swagger
ns’s are used in the json-schema / swagger transformations
yes
was doing something like
(s/def ::clj-time (s/with-gen #(instance? DateTime (from-string %))
#(s/gen #{"2018-01-01" "2018-01-02"})))
adding all the possible data (encoder, decoder, gen, example, swagger-info etc.) means a lot of data, but then again, it’s just data and every bit has it’s own use case.
btw in your example is it encode/json
or decode/json
?
btw, the swagger-spec-transformer uses json-schema-spec-transformer under the hoods, so with swagger, it merges the swagger
namespaced over the json-schema
namespaced.
oh, should be decode/json
as it’s string->date. good catch!
👍 we like compojure-api 😉
one more thing @ikitommi, the ::date spec is working but apparently I can’t compose it :
(s/def ::somemap (s/map-of ::date ::string))
I can check with s/explain
but going to the api it doesn’t conform
@mping map-of
doesn't conform keys by default. You need to pass in some option to it, can't recall, but found in it's docstring
it didn’t work; it’s :conform-keys true
but apparently it’s receiving a keyword
I should try disabling wrap-keyword-params
or maybe with the json parser
oh, I would do that in the :decode/json
e.g. take the name
if it's a keyword.
got it! working