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"

может быть, такой?

\"x\"\s:\s\"([^"]*?)\"

это не глядя буквы. Просто жду цитаты