Закрытое построение URL из составных частей - PullRequest
13 голосов
/ 05 сентября 2010

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

Ответы [ 5 ]

19 голосов
/ 05 сентября 2010

Существует функция url-encode в пространстве имен Ring * ring.util.codec:

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

Обновление:

Возможно, модифицированная версия могла бы сделать более дружественным к Clojure.Также обрабатывает кодирование через необязательный аргумент в стиле Ring с 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"
12 голосов
/ 05 сентября 2010

Вот один из способов:

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/clojure@googlegroups.com/msg29338.html

Код оттуда позволит вам сделать это:

user=> (encode-params {"q" "clojure url"})
"q=clojure+url"
11 голосов
/ 01 февраля 2011

Это точный эквивалент 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, то есть.

2 голосов
/ 05 сентября 2010

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"
0 голосов
/ 05 сентября 2010

Простое решение с использованием str (ings):

(def q (str "clojure+url"))
(def url (str "http://stackoverflow.com/search?" q))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...