Unescape unicode в символьной строке
существует давно ошибка на RJSONIO
для разбора строк json, содержащих escape-последовательности unicode. Похоже, что ошибка должна быть исправлена в libjson
которые, возможно, не произойдет в ближайшее время, так что я ищу в создании обходного пути в R, которая отменяет uxxxx
последовательности Перед подачей их в парсер json.
некоторый контекст: данные json всегда unicode, используя utf-8
по умолчанию, поэтому, как правило, нет необходимости в экранировании. Но для исторического причины, json поддерживает экранированный unicode. Следовательно, данные json
{"x" : "Zürich"}
и
{"x" : "Zu00FCrich"}
эквивалентны и должны привести к точно такой же результат при анализе. Но по какой-то причине последнее не работает в RJSONIO
. Дополнительные путаница вызвано тем, что сам R также поддерживает экранированный unicode. Поэтому, когда мы набираем "Zu00FCrich"
в консоли R он автоматически правильно преобразуется в "Zürich"
. Чтобы получить фактическую строку json под рукой нам нужно избежать самой обратной косой черты, которая является первым символом escape-последовательности unicode в json:
test <- '{"x" : "Zu00FCrich"}'
cat(test)
Итак, мой вопрос: учитывая большую строку json в R, как я могу отменить все экранированные последовательности unicode? Т. е. как заменить все вхождения uxxxx
соответствующим символом Юникода? Опять же,uxxxx
здесь представлена фактическая строка из 6 символов, начинающаяся с обратной косой черты. Так что
3 ответов
после игры с этим еще немного я думаю, что лучшее, что я могу сделать, это поиск \uxxxx
шаблоны с использованием регулярного выражения, а затем проанализировать те, используя парсер R:
unescape_unicode <- function(x){
#single string only
stopifnot(is.character(x) && length(x) == 1)
#find matches
m <- gregexpr("(\\)+u[0-9a-z]{4}", x, ignore.case = TRUE)
if(m[[1]][1] > -1){
#parse matches
p <- vapply(regmatches(x, m)[[1]], function(txt){
gsub("\", "\\", parse(text=paste0('"', txt, '"'))[[1]], fixed = TRUE, useBytes = TRUE)
}, character(1), USE.NAMES = FALSE)
#substitute parsed into original
regmatches(x, m) <- list(p)
}
x
}
это, кажется, работает для всех случаев, и я еще не нашел каких-либо странных побочных эффектов
для этого есть функция в stringi
пакет :)
require(stringi)
escaped <- "Z\u00FCrich"
escaped
## [1] "Z\u00FCrich"
stri_unescape_unicode(escaped)
## [1] "Zürich"