2010-09-04 13 views
12

In Python ich folgende tun würde:Clojure Bau von URL von Bestandteilen

>>> q = urllib.urlencode({"q": "clojure url"}) 
>>> q 
'q=clojure+url' 

>>> url = "http://stackoverflow.com/search?" + q 
>>> url 
'http://stackoverflow.com/search?q=clojure+url' 

Wie kann ich alles tun, die Codierung, die für mich oben in Clojure getan hat? Mit anderen Worten: Wie kann ich tun, so etwas wie die folgenden:

=> (build-url "http://stackoverflow.com/search" {"q" "clojure url"}) 
"http://stackoverflow.com/search?q=clojure+url" 

Antwort

12

Hier ist eine Art und Weise:

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" 

Ich weiß, Das ist jedoch nicht genau dasselbe wie dein Python-Snippet. Bitte beachten Sie die folgenden Beitrag aus der Clojure Mailingliste für eine vollständigere Antwort:

http://www.mail-archive.com/[email protected]/msg29338.html

Der Code von dort können Sie dies tun:

user=> (encode-params {"q" "clojure url"}) 
"q=clojure+url" 
+0

Da ich den Schnitt bemerkt habe, hätte ich mir wahrscheinlich nicht die Mühe gemacht, all das zu schreiben ... Na gut. +1 für die erste vollständige Antwort. Ich mag immer noch meine 'Named'-Handling-Version, also verlasse ich das hier. :-) –

0

Eine einfache Lösung mit str (ings):

(def q (str "clojure+url")) 
(def url (str "http://stackoverflow.com/search?" q)) 
+0

Nun, Sie geben '+' als Eingabe, damit Sie Clojure nicht tatsächlich die Zeichenfolge für Sie codieren lassen. –

18

Es gibt eine url-encode Funktion in Rings ring.util.codec Namespace:

(ring.util.codec/url-encode "clojure url") 
; => "clojure+url" 

bin ich nicht sicher, ob es eine Vorverpackung Funktion, um eine Karte in eine quer drehen y string, aber vielleicht könnte dies die Arbeit machen:

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

Ein Beispiel:

user> (make-query-string {"q" "clojure url" "foo" "bar"}) 
"q=clojure+url&foo=bar" 

Alles, was das Ergebnis auf das Ende einer URL bleibt ist verketten:

(defn build-url [url-base query-map] 
    (str url-base "?" (make-query-string query-map))) 

Scheint zu arbeiten:

user> (build-url "http://stackoverflow.com/search" {"q" "clojure url"}) 
"http://stackoverflow.com/search?q=clojure+url" 

Update:

Vielleicht eine modifizierte Version für eine Clojure freundliche Erfahrung machen könnte. Behandelt auch die Codierung über ein Ring-optionales Argument mit utf-8 als Standard.

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

jetzt So können wir

tun
user> (build-url "http://example.com/q" {:foo 1}) 
"http://example.com/q?foo=1" 
+0

Ah, fast vergessen: 'ring.util.codec' nimmt auch ein optionales Kodierungsargument, standardmäßig 'UTF-8'. –

2

clj-apache-http ziemlich nützlich ist. Mit ihm können Sie folgendes tun:

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

Dies ist das genaue REPL Äquivalent Ihrer Python-Session, mit 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" 

aber CLJ-http macht es noch einfacher:

user=> (client/get "http://stackoverflow.com/search?" 
user=*    {:query-params {"q" "clojure url"}}) 
... <a lot of output, omitted to protect the innocent>... 

davon aus, dass Sie eine GET-Anforderung durchführen möchten, das ist.