Search code examples
clojuretype-conversionringcompojure

Is there some way to let compojure support type conversion automatically?


Now can use compojure this way:

(GET ["/uri"] [para1 para2]
   )

Para1 and para2 are all of type String.

I would like to let it know the type correcttly,like this:

(GET ["/uri"] [^String para1 ^Integer para2]
   )

It can convert para1 to be Sting and para2 to Integer.

Is there some library or good way to do this?


Solution

  • This is not currently possible with only Compojure.

    You could use Prismatic schema coercion.

    (require '[schema.core :as s])
    (require '[schema.coerce :as c])
    (require '[compojure.core :refer :all])
    (require '[ring.middleware.params :as rparams])
    
    (def data {:para1 s/Str :para2 s/Int s/Any s/Any})
    (def data-coercer (c/coercer data c/string-coercion-matcher ))
    
    (def get-uri
      (GET "/uri" r
            (let [{:keys [para1 para2]}  (data-coercer (:params r))]
                     (pr-str {:k1 para1 :k2 (inc para2)}))))
    
    (def get-uri-wrapped
      (let [keywordizer (fn [h]
                          (fn [r]
                            (h (update-in r [:params] #(clojure.walk/keywordize-keys %)))))]
        (-> get-uri keywordizer rparams/wrap-params)))
    

    Here is a sample run:

    (get-uri-wrapped {:uri "/uri" :query-string "para1=a&para2=3" :request-method :get})
    
    {:status 200,
     :headers {"Content-Type" "text/html; charset=utf-8"},
     :body "{:k1 \"a\", :k2 4}"}