Fork me on GitHub
#ring-swagger
<
2019-01-11
>
mping11:01:57

Hi, how do you guys apply spec for dates? specifically with clj-time if possible?

mping11:01:04

I’m using compojure-api

mping11:01:32

I want to coerce strings to clj-time dates

valtteri12:01:58

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.

valtteri12:01:40

Time will show how much pain this approach causes.

5
ikitommi13:01:13

doesn’t inst? predicate just work?

ikitommi13:01:24

(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"

ikitommi13:01:46

I guess clj-time (joda) would require custom Specs to work. But that should be relatively straightforward to do?

mping13:01:50

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

ikitommi13:01:01

what does nice in swagger mean?

ikitommi13:01:29

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"}))

ikitommi13:01:41

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"}))

mping13:01:57

oh thats pretty cool

mping13:01:08

nice means the example value gets generated correctly

ikitommi13:01:15

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

mping13:01:00

was doing something like

(s/def ::clj-time (s/with-gen #(instance? DateTime (from-string %))
                              #(s/gen #{"2018-01-01" "2018-01-02"})))

ikitommi13:01:23

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.

mping13:01:36

btw in your example is it encode/json or decode/json

ikitommi13:01:56

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.

ikitommi14:01:10

oh, should be decode/json as it’s string->date. good catch!

mping14:01:34

👍 we like compojure-api 😉

👍 5
😉 5
mping14:01:08

one more thing @ikitommi, the ::date spec is working but apparently I can’t compose it : (s/def ::somemap (s/map-of ::date ::string))

mping14:01:28

I can check with s/explain but going to the api it doesn’t conform

ikitommi15:01:24

@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

mping15:01:15

it didn’t work; it’s :conform-keys true

mping15:01:25

but apparently it’s receiving a keyword

mping15:01:39

I should try disabling wrap-keyword-params

mping15:01:52

or maybe with the json parser

ikitommi15:01:09

oh, I would do that in the :decode/json

ikitommi15:01:30

e.g. take the name if it's a keyword.

mping15:01:15

got it! working