Używanie JSON.decode
do tego ma istotne wady, o których musisz wiedzieć:
- Musisz zawinąć ciąg w podwójne cudzysłowy
- Wiele postaci nie jest obsługiwanych i same muszą przed nimi uciec. Na przykład, przekazując dowolną z następujących czynności
JSON.decode
(po owijanie ich w cudzysłów) będzie błędu, mimo wszystko to są ważne: \\n
, \n
, \\0
,a"a
- Nie obsługuje znaków szesnastkowych:
\\x45
- Nie obsługuje sekwencji punktów kodowych Unicode:
\\u{045}
Istnieją również inne zastrzeżenia. Zasadniczo używanie JSON.decode
do tego celu jest hackowaniem i nie działa tak, jak można się zawsze spodziewać. Należy trzymać się JSON
biblioteki do obsługi formatu JSON, a nie operacji na łańcuchach.
Niedawno napotkałem ten problem i chciałem solidnego dekodera, więc napisałem go sam. Jest kompletny, dokładnie przetestowany i dostępny tutaj: https://github.com/iansan5653/unraw . Naśladuje standard JavaScript tak dokładnie, jak to możliwe.
Wyjaśnienie:
Źródło ma około 250 linii, więc nie będę go tutaj umieszczać, ale zasadniczo używa następującego Regex, aby znaleźć wszystkie sekwencje specjalne, a następnie analizuje je, używając parseInt(string, 16)
do dekodowania liczb o podstawie 16, a następnie String.fromCodePoint(number)
do uzyskania odpowiedniego znaku:
/\\(?:(\\)|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
Skomentowano (UWAGA: to wyrażenie regularne pasuje do wszystkich sekwencji ucieczki, w tym nieprawidłowych. Jeśli ciąg spowodowałby błąd w JS, zgłasza błąd w mojej bibliotece [tj. '\x!!'
Spowoduje błąd]):
/
\\ # 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
Przykład
Korzystanie z tej biblioteki:
import unraw from "unraw";
let step1 = unraw('http\\u00253A\\u00252F\\u00252Fexample.com');
let step2 = decodeURIComponent(step1);