我在处理R中的转义unicode字符时遇到问题,特别是在从MediaWiki API获取信息时遇到的问题。我会找到像
这样的JSON字符串{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}}
哪个应该是完全有效的,但通过fromJSON()
读入时,我得到:
snip...
[1] "Banach\023Tarski paradox"
最初我认为这只是RJSONIO的一个问题,但我遇到scan()
和readLines()
的类似问题。我的猜测是我遗漏了一些非常基本的东西。
我实际上无法使用仅 R给出完全可重现的示例,因为如果我通过write()(或某些等效函数)将“em \ u2013dash”发送到文件,R将自动转换为他们冲刺。所以这里。使用以下命令创建名为test1的文本文件:
"em\u2013dash" "em–dash" " em \u2013 dash"
然后加载R(无论文件路径是什么):
> scan( file = "~/R/test1", what = "character", encoding = "UTF-8")
Read 3 items
[1] "em\\u2013dash" "em–dash" " em \\u2013 dash"
> readLines("~/R/test1", warn = FALSE, encoding = "UTF-8")
[1] "\"em\\u2013dash\" \"em–dash\" \" em \\u2013 dash\""
添加的转义字符是导致fromJSON()
出现问题的原因。我可以把它们剥离出来,但我可能会在这个过程中打破其他东西,我想有一个更简单的解决方案。谢谢。
以下是会话信息:
R version 2.14.1 (2011-12-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
locale:
[1] C/en_US.UTF-8/C/C/C/C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] RJSONIO_0.98-0
loaded via a namespace (and not attached):
[1] tools_2.14.1
答案 0 :(得分:9)
这实际上不是RJSONIO中的错误。它的设计目的是期望一个由R读取并且已经处理过非ASCII字符的字符串。当一个字符串传递一个带有\ u的字符串时,该字符串尚未处理但已转义。 在我的机器上,语言环境设置为en_US.UTF-8,命令
fromJSON('{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}}')
产生
$query
$query$categorymembers
$query$categorymembers[[1]]
$query$categorymembers[[1]]$ns
[1] 0
$query$categorymembers[[1]]$title
[1] "Banach–Tarski paradox"
请注意,该字符的前缀为\u
而不是\\u
。
只需输入该字符串,即可查看它在R中的显示方式。
所以问题是fromJSON()的上游,为什么字符串包含\ u。
我可以在RJSONIO中添加对处理此类未处理字符串的支持。
答案 1 :(得分:5)
这是RJSONIO
中的错误,因为您可以清楚地看到:
> RJSONIO::fromJSON('{"x":"foo\\u2013bar"}')
x
"foo\023bar"
在rjson
:
> rjson::fromJSON('{"x":"foo\\u2013bar"}')
$x
[1] "foo–bar"
并证明它是正确的值:
> Sys.setlocale("LC_ALL", "C")
[1] "C/C/C/C/C/en_US.UTF-8"
> rjson::fromJSON('{"x":"foo\\u2013bar"}')
$x
[1] "foo<U+2013>bar"
在您的分析中,您对打印字符串与实际字符串感到困惑。 print
引用其内容进行打印 - 如果要查看实际字符串,可以使用cat
或charToRaw
。此外scan
不解释任何逃脱,所以你得到你给它的东西。
答案 2 :(得分:1)
我认为根本问题是libjson
中未启用RJSONIO
选项JSON_UNICODE
。但是,当输入为UTF-8
编码时,似乎问题并未表现出来:
library(RJSONIO)
x = "北京填鴨们"
identical(x, fromJSON(toJSON(x)))
# [1] TRUE
仅当输入使用JSON转义字符时才会出现此问题。在这些情况下,RJSONIO
似乎会生成latin1
输出,但不会标记正确设置编码:
x <- fromJSON('["Z\\u00FCrich"]')
print(x)
# [1] "Z\xfcrich"
nchar(x)
#Error in nchar(x) : invalid multibyte string 1
对于这个简单的示例,我们可以通过手动将编码设置为latin1
来修复它:
#Set the correct encoding
Encoding(x) <- "latin1"
print(x)
#[1] "Zürich"
但是,这当然不适用于latin1
集之外的字符:
#This should be: "填"
fromJSON('["\\u586B"]')