Clojure построение URL из составных частей
В Python я бы сделал следующее:
>>> q = urllib.urlencode({"q": "clojure url"})
>>> q
'q=clojure+url'
>>> url = "http://stackoverflow.com/search?" + q
>>> url
'http://stackoverflow.com/search?q=clojure+url'
Как мне сделать все кодирование, сделанное для меня выше в Clojure? Другими словами, как мне сделать что-то похожее на следующее:
=> (build-url "http://stackoverflow.com/search" {"q" "clojure url"})
"http://stackoverflow.com/search?q=clojure+url"
Ответы
Ответ 1
Здесь один из способов:
user=> (import [java.net URLEncoder])
java.net.URLEncoder
user=> (str "http://stackoverflow.com/search?q=" (URLEncoder/encode "clojure url" "UTF-8"))
"http://stackoverflow.com/search?q=clojure+url"
Я знаю, что это не совсем то же самое, что и ваш фрагмент Python. Пожалуйста, просмотрите следующее сообщение из списка рассылки Clojure для получения более полного ответа:
http://www.mail-archive.com/[email protected]/msg29338.html
Код оттуда позволит вам сделать это:
user=> (encode-params {"q" "clojure url"})
"q=clojure+url"
Ответ 2
В кольцевом пространстве ring.util.codec
есть функция url-encode
:
(ring.util.codec/url-encode "clojure url")
; => "clojure+url"
Я не уверен, есть ли предварительно упакованная функция, чтобы превратить карту в строку запроса, но, возможно, это могло бы выполнить задание:
(use '[ring.util.codec :only [url-encode]])
(defn make-query-string [m]
(->> (for [[k v] m]
(str (url-encode k) "=" (url-encode v)))
(interpose "&")
(apply str)))
Пример:
user> (make-query-string {"q" "clojure url" "foo" "bar"})
"q=clojure+url&foo=bar"
Все, что остается, это объединение результата в конец URL-адреса:
(defn build-url [url-base query-map]
(str url-base "?" (make-query-string query-map)))
Кажется, работает:
user> (build-url "http://stackoverflow.com/search" {"q" "clojure url"})
"http://stackoverflow.com/search?q=clojure+url"
Update:
Возможно, модифицированная версия может сделать более приятным Clojure. Также обрабатывает кодировку с помощью необязательного аргумента Ring-style с utf-8 по умолчанию.
(defn make-query-string [m & [encoding]]
(let [s #(if (instance? clojure.lang.Named %) (name %) %)
enc (or encoding "UTF-8")]
(->> (for [[k v] m]
(str (url-encode (s k) enc)
"="
(url-encode (str v) enc)))
(interpose "&")
(apply str))))
(defn build-url [url-base query-map & [encoding]]
(str url-base "?" (make-query-string query-map encoding)))
Итак, теперь мы можем сделать
user> (build-url "http://example.com/q" {:foo 1})
"http://example.com/q?foo=1"
Ответ 3
Это точный эквивалент REPL вашего сеанса python, используя clj-http.
user=> (require ['clj-http.client :as 'client])
nil
user=> (str "http://stackoverflow.com/search?"
user=* (client/generate-query-string {"q" "clojure url"}))
"http://stackoverflow.com/search?q=clojure+url"
но clj-http делает это еще проще:
user=> (client/get "http://stackoverflow.com/search?"
user=* {:query-params {"q" "clojure url"}})
... <a lot of output, omitted to protect the innocent>...
предполагая, что вы хотите выполнить запрос GET, то есть.
Ответ 4
clj-apache-http довольно полезно. С его помощью вы можете сделать следующее:
user=> (require ['com.twinql.clojure.http :as 'http])
nil
user=> (def q (http/encode-query {"q" "clojure url"}))
#'user/q
user=> (def url (str "http://stackoverflow.com/search?" q))
#'user/url
user=> url
"http://stackoverflow.com/search?q=clojure+url"
Ответ 5
Простое решение с использованием str (ings):
(def q (str "clojure+url"))
(def url (str "http://stackoverflow.com/search?" q))