字符串中的Unescape unicode

Jer*_*oen 8 regex unicode json r utf-8

有一个长期的错误RJSONIO解析包含Unicode转义序列JSON字符串.似乎需要修复bug,libjson这可能不会很快发生,因此我正在寻找在R中创建一个解决方法,\uxxxx在将它们提供给json解析器之前对其进行unescapes 序列.

一些上下文:json数据总是unicode,utf-8默认使用,因此通常不需要转义.但由于历史原因,json确实支持转义的unicode.因此json数据

{"x" : "Zürich"}
Run Code Online (Sandbox Code Playgroud)

{"x" : "Z\u00FCrich"}
Run Code Online (Sandbox Code Playgroud)

是等价的,并且在解析时应该产生完全相同的输出.但无论出于何种原因,后者都不起作用RJSONIO.另外一个混乱是由于R本身也支持转义的unicode.因此,当我们输入"Z\u00FCrich"R控制台时,它会自动正确转换为"Zürich".为了获得实际的json字符串,我们需要转义反斜杠本身,它是json中unicode转义序列的第一个字符:

test <- '{"x" : "Z\\u00FCrich"}'
cat(test)
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:在R中给出一个大的json字符串,我怎样才能解除所有转义的unicode序列?即我如何\uxxxx用相应的unicode字符替换所有出现的?同样,\uxxxx这里表示一个6个字符的实际字符串,以反斜杠开头.所以一个unescape函数应该满足:

#Escaped string
escaped <- "Z\\u00FCrich"

#Unescape unicode
unescape(escaped) == "Zürich"

#This is the same thing
unescape(escaped) == "Z\u00FCrich"
Run Code Online (Sandbox Code Playgroud)

可能使事情复杂化的一件事是,如果反斜杠本身在json中使用另一个反斜杠进行转义,则它不是 unicode转义序列的一部分.例如,unescape还应满足:

#Watch out for escaped backslashes
unescape("Z\\\\u00FCrich") == "Z\\\\u00FCrich"
unescape("Z\\\\\\u00FCrich") == "Z\\\\ürich"
Run Code Online (Sandbox Code Playgroud)

Jer*_*oen 5

在玩了一些之后,我认为我能做的最好的就是\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
}
Run Code Online (Sandbox Code Playgroud)

这似乎适用于所有情况,我还没有发现任何奇怪的副作用