Fork me on GitHub
#ring-swagger
<
2016-01-25
>
ljosa20:01:54

I'm trying to make a GET route with a query parameter that can be either a Long or a Date. I have

(GET* "/history" []
                :summary "Get the transaction history diffs of the database"
                :query-params [{begin :- TimePoint nil} {end :- TimePoint nil} {limit :- Long 50} {offset :- Long 0}]
                :return s/Any
                …
and
(s/defschema TimePoint
  (s/maybe (s/either java.util.Date Long)))
However, when I do curl -s -G -d begin=1598495 -d limit=2 http://…, my number is not converted from String to Long, and I get this:
{"errors":{"begin":"(not (some-matching-either-clause? \"1598495\"))"}}
Is there a way to get it to convert (as it does if I specify just Long instead of TimePoint—but then I lose the ability to pass either a number or a date)?

juhoteperi20:01:00

Query parameters will be strings so they would have to be coerced to Long or Date. Either Schema doesn't support coercion.

ikitommi20:01:52

@juhoteperi ideas how that could be implemented? With cond-pre maybe?

ikitommi20:01:20

or a custom coercer?

ikitommi20:01:20

If a TimePoint would just be a Date and one would add a Long->Date matcher to string-coercer.. might work. Not near a computer, can't test thou.

juhoteperi20:01:27

I don't know how conditional works with coercion and I don't know what kind of predicate it would need

ljosa21:01:29

the Long in this case is a Datomic database t, so it needs to stay a Long.

ljosa21:01:15

I'm trying stuff like this, but haven't gotten it to quite work in context yet:

(s/defschema TimePoint
  (s/maybe (s/either java.util.Date Long)))

(defn timepoint-matcher [schema]
  (when (= schema TimePoint)
    (fn [x]
      (if (= x "")
        nil
        (or (try
              (Long/parseLong x)
              (catch NumberFormatException e nil))
            (clojure.instant/read-instant-date x))))))

(def timepoint-coercer (coerce/coercer TimePoint timepoint-matcher))