RJSONIO
中有一个长期bug用于解析包含unicode转义序列的json字符串。看起来这个bug需要在libjson
中修复,这可能不会很快发生,所以我正在寻找在R中创建一个解决方法,在将它们提供给json解析器之前,它们会先发现\uxxxx
个序列。 / p>
某些上下文:json数据始终是unicode,默认使用utf-8
,因此通常不需要转义。但由于历史原因,json确实支持转义的unicode。因此json数据
{"x" : "Zürich"}
和
{"x" : "Z\u00FCrich"}
是等效的,并且在解析时应该产生完全相同的输出。但无论出于何种原因,后者在RJSONIO
中都不起作用。额外的confusion是由R本身也支持转义的unicode引起的。因此,当我们在R控制台中键入"Z\u00FCrich"
时,它会自动正确转换为"Zürich"
。要获取实际的json字符串,我们需要转义反斜杠本身,它是json中unicode转义序列的第一个字符:
test <- '{"x" : "Z\\u00FCrich"}'
cat(test)
所以我的问题是:在R中给出一个大的json字符串,我怎样才能解除所有转义的unicode序列?即如何用相应的unicode字符替换所有出现的\uxxxx
?同样,这里的\uxxxx
表示一个由6个字符组成的实际字符串,以反斜杠开头。因此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"
答案 0 :(得分: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
}
这似乎适用于所有病例,我还没有发现任何奇怪的副作用
答案 1 :(得分:2)
stringi
包中有一个函数:)
require(stringi)
escaped <- "Z\\u00FCrich"
escaped
## [1] "Z\\u00FCrich"
stri_unescape_unicode(escaped)
## [1] "Zürich"
答案 2 :(得分:1)
也许是这样的?
\"x\"\s:\s\"([^"]*?)\"
这不是看信。等待报价