在解析包含unicode转义序列的json字符串时,存在一个长期存在的错误RJSONIO。似乎需要修复该错误,这种错误libjson可能很快就不会发生,因此我正在寻找一种在R中创建解决方法的方法,该方法在将\uxxxx序列提供给json解析器之前先取消序列化。
RJSONIO
libjson
\uxxxx
一些上下文:json数据始终是unicode,utf-8默认情况下使用,因此通常不需要转义。但是出于历史原因,json确实支持转义的unicode。因此json数据
utf-8
{"x" : "Zürich"}
和
{"x" : "Z\u00FCrich"}
是等效的,并且在解析时应产生完全相同的输出。但是无论出于什么原因,后者都不起作用RJSONIO。R本身也支持转义的unicode,这引起了进一步的混乱。因此,当我们输入"Z\u00FCrich"R控制台时,它会自动正确转换为"Zürich"。为了获得实际的json字符串,我们需要转义反斜杠本身,它是json中unicode转义序列的第一个字符:
"Z\u00FCrich"
"Zürich"
test <- '{"x" : "Z\\u00FCrich"}' cat(test)
所以我的问题是:给定R中的一个大json字符串,我该如何对所有转义的unicode序列进行转义?即我如何\uxxxx用相应的unicode字符替换所有出现的?同样,\uxxxx这里代表一个以反斜杠开头的6个字符的实际字符串。因此,一个unescape函数应该满足:
unescape
#Escaped string escaped <- "Z\\u00FCrich" #Unescape unicode unescape(escaped) == "Zürich" #This is the same thing unescape(escaped) == "Z\u00FCrich"
可能使事情复杂化的一件事是,如果反斜杠本身在json中与另一个反斜杠一起转义,则它 不是 Unicode转义序列的一部分。例如,unescape还应满足:
#Watch out for escaped backslashes unescape("Z\\\\u00FCrich") == "Z\\\\u00FCrich" unescape("Z\\\\\\u00FCrich") == "Z\\\\ürich"
在玩了更多之后,我认为我能做的最好的就是\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 }
这似乎适用于所有情况,我还没有发现任何奇怪的副作用