L'utilizzo JSON.decode
per questo comporta svantaggi significativi di cui devi essere a conoscenza:
- È necessario racchiudere la stringa tra virgolette doppie
- Molti caratteri non sono supportati e devono essere salvati da soli. Ad esempio, passando una delle seguenti a
JSON.decode
(dopo avvolgendoli in doppi apici) sarà errore anche se questi sono tutti validi: \\n
, \n
, \\0
,a"a
- Non supporta gli escape esadecimali:
\\x45
- Non supporta sequenze di punti di codice Unicode:
\\u{045}
Ci sono anche altri avvertimenti. In sostanza, l'utilizzo JSON.decode
per questo scopo è un trucco e non funziona nel modo in cui potresti sempre aspettarti. Dovresti continuare a usare la JSON
libreria per gestire JSON, non per le operazioni sulle stringhe.
Di recente mi sono imbattuto in questo problema e volevo un decoder robusto, quindi ho finito per scriverne uno io stesso. È completo e accuratamente testato ed è disponibile qui: https://github.com/iansan5653/unraw . Imita lo standard JavaScript il più fedelmente possibile.
Spiegazione:
La fonte è di circa 250 righe, quindi non includerò tutto qui, ma essenzialmente utilizza il seguente Regex per trovare tutte le sequenze di escape e quindi le analizza usando parseInt(string, 16)
per decodificare i numeri in base 16 e quindi String.fromCodePoint(number)
per ottenere il carattere corrispondente:
/\\(?:(\\)|x([\s\S]{0,2})|u(\{[^}]*\}?)|u([\s\S]{4})\\u([^{][\s\S]{0,3})|u([\s\S]{0,4})|([0-3]?[0-7]{1,2})|([\s\S])|$)/g
Commentato (NOTA: questa regex corrisponde a tutte le sequenze di escape, comprese quelle non valide. Se la stringa genera un errore in JS, genera un errore nella mia libreria [cioè, '\x!!'
errore]):
/
\\ # All escape sequences start with a backslash
(?: # Starts a group of 'or' statements
(\\) # If a second backslash is encountered, stop there (it's an escaped slash)
| # or
x([\s\S]{0,2}) # Match valid hexadecimal sequences
| # or
u(\{[^}]*\}?) # Match valid code point sequences
| # or
u([\s\S]{4})\\u([^{][\s\S]{0,3}) # Match surrogate code points which get parsed together
| # or
u([\s\S]{0,4}) # Match non-surrogate Unicode sequences
| # or
([0-3]?[0-7]{1,2}) # Match deprecated octal sequences
| # or
([\s\S]) # Match anything else ('.' doesn't match newlines)
| # or
$ # Match the end of the string
) # End the group of 'or' statements
/g # Match as many instances as there are
Esempio
Utilizzando quella libreria:
import unraw from "unraw";
let step1 = unraw('http\\u00253A\\u00252F\\u00252Fexample.com');
let step2 = decodeURIComponent(step1);