Unescaping caratteri di una stringa con Ruby
Domanda
Data una stringa nel formato seguente (le Posterous restituisce API messaggi in questo formato):
s="\\u003Cp\\u003E"
Come faccio a convertirlo in caratteri ASCII effettivi tale che s="<p>"
?
Iconv.iconv('ascii', 'java', s)
su OSX, ho usato con successo, ma una volta schierato a Heroku, ricevo un'eccezione Iconv::IllegalSequence
. Sto indovinando che il sistema Heroku distribuisce al does't sostenere l'encoder java
.
HTTParty per fare una richiesta alle API Posterous. Se uso curl per fare la stessa richiesta poi faccio non ottenere le doppie barre.
Da HTTParty github pagina:
automatico il parsing di JSON e XML in hash rubino basati sulla risposta tipo di contenuto
L'API Posterous restituisce JSON (senza doppie barre) e HTTParty di JSON parsing è l'inserimento della doppia barra.
Ecco un semplice esempio del modo in cui sto usando HTTParty per effettuare la richiesta.
class Posterous
include HTTParty
base_uri "http://www.posterous.com/api/2"
basic_auth "username", "password"
format :json
def get_posts
response = Posterous.get("/users/me/sites/9876/posts&api_token=1234")
# snip, see below...
end
end
Con le informazioni ovvio (nome utente, password, site_id, api_token) sostituiti con valori validi.
Al punto di cesoiatura, response.body
contiene una stringa rubino che è in formato JSON e response.parsed_response
contiene un oggetto hash rubino che HTTParty creato analizzando la risposta JSON dall'API Posterous.
In entrambi i casi le sequenze unicode come \u003C
sono stati cambiati per \\u003C
.
Soluzione
mi sono imbattuto in questo problema esatto, l'altro giorno. C'è un bug nel parser JSON che HTTParty utilizza (Crack gemma) - in fondo si usa un'espressione regolare tra maiuscole e minuscole per le sequenze Unicode, perché Posterous mette fuori A-F al posto di un-f, Crack è non li unescaping. Ho presentato una richiesta di pull per risolvere questo problema.
Nel frattempo HTTParty ben consente di specificare parser alternati in modo da poter fare ::JSON.parse
bypassando Crack del tutto simile a questo:
class JsonParser < HTTParty::Parser
def json
::JSON.parse(body)
end
end
class Posterous
include HTTParty
parser ::JsonParser
#....
end
Altri suggerimenti
Ho trovato una soluzione a questo problema. Mi sono imbattuto in questo Gist . elskwid avuto il problema identico e corse la stringa attraverso un parser JSON:
s = ::JSON.parse("\\u003Cp\\u003E")
Ora, s = "<p>"
.
È inoltre possibile utilizzare pack
:
"a\\u00e4\\u3042".gsub(/\\u(....)/){[$1.hex].pack("U")} # "aäあ"
O, per fare il contrario:
"aäあ".gsub(/[^ -~\n]/){"\\u%04x"%$&.ord} # "a\\u00e4\\u3042"
I-backslash raddoppiato quasi l'aspetto di una stringa regolare sta visualizzando in un debugger.
Il "\u003Cp\u003E"
stringa è in realtà "<p>"
, solo il \u003C
è Unicode per <
e \003E
è >
.
>> "\u003Cp\u003E" #=> "<p>"
Se siete veramente trovato la stringa con backslash raddoppiati allora si potrebbe provare a nudo uno dei due.
Come prova, vedere quanto tempo la stringa è:
>> "\\u003Cp\\u003E".size #=> 13
>> "\u003Cp\u003E".size #=> 3
>> "<p>".size #=> 3
Tutto ciò è stato fatto con rubino 1.9.2, che è a conoscenza di Unicode. v1.8.7 non era. Ecco quello che ottengo utilizzando IRB 1.8.7 del confronto:
>> "\u003Cp\u003E" #=> "u003Cpu003E"