4

次の JSON ファイル ("my_file.json") を R に読み込もうとしています。

[{"id":"484","comment":"They call me "Bruce""}]

jsonlite パッケージ (0.9.12) を使用すると、次のエラーが発生します。

library(jsonlite)
fromJSON(readLines('~/my_file.json'))

エラーを受け取る:

"Error in parseJSON(txt) : lexical error: invalid char in json text.
84","comment":"They call me "Bruce""}]
           (right here) ------^"

ファイルの R エスケープからの出力は次のとおりです。

readLines('~/my_file.json')

"[{\"id\":\"484\",\"comment\":\"They call me \"Bruce\"\"}]"

次のように、「Bruce」を囲む引用符を削除すると、問題が解決します。

my_file.json

[{"id":"484","comment":"They call me Bruce"}]

しかし、脱進機の問題は何ですか?

4

1 に答える 1

8

R文字列リテラルでは、一重引用符または二重引用符を使用して定義できます。
例えば

s1 <- 'hello'
s2 <- "world"

もちろん、二重引用符を使用して定義された文字列リテラル内に二重引用符を含めたい場合は、内側の引用符を (バックスラッシュを使用して) エスケープする必要があります。そうしないと、R コード パーサーは文字列の末尾を正しく検出できません (一重引用符の場合も同様です)。
例えば

s1 <- "Hello, my name is \"John\""

この文字列を (¹ を使用してcat) コンソールに出力するか、この文字列をファイルに書き込むと、R リテラル表現ではなく、文字列の実際の「顔」が得られます。

> cat("Hello, my name is \"John\"")
Hello, my name is "John"

jsonパーサーは、文字列の実際の「顔」を読み取るため、あなたの場合、jsonは次のように読み取ります:

[{"id":"484","comment":"They call me "Bruce""}]

not (R リテラル表現) :

"[{\"id\":\"484\",\"comment\":\"They call me \"Bruce\"\"}]" 

そうは言っても、文字列内に引用符がある場合、json パーサーでも二重引用符をエスケープする必要があります。

したがって、文字列は次のように変更する必要があります。

[{"id":"484","comment":"They call me \"Bruce\""}]

バックスラッシュを追加してファイルを変更するだけで、json を完全に読み取ることができます。

その文字列の対応する R リテラル表現は次のようになることに注意してください。

"[{\"id\":\"484\",\"comment\":\"They call me \\\"Bruce\\\"\"}]"

実際、これは機能します:

> fromJSON("[{\"id\":\"484\",\"comment\":\"They call me \\\"Bruce\\\"\"}]")
   id              comment
1 484 They call me "Bruce"

¹ デフォルトの Rprint関数 (値に対して ENTER を押すだけでも呼び出される) は、対応する R 文字列リテラルを返します。実際の文字列を出力したい場合はprint(quote=F,stringToPrint)、またはcat関数を使用する必要があります。


EDIT(引用符のエスケープを自動化する可能性に関する@EngrStudentコメントについて):

Json パーサーは引用符を自動的にエスケープできません。
つまり、コンピューターの立場になって、この (エスケープされていない) 文字列を json として解析する必要があるとイメージしてみてください。{ "foo1" : " : "foo2" : "foo3" }

有効な json を与える少なくとも 3 つの可能なエスケープが表示されます。
{ "foo1" : " : \"foo2\" : \"foo3" }
{ "foo1\" : " : "foo2\" : \"foo3" }
{ "foo1\" : \" : \"foo2" : "foo3" }

この小さな例からわかるように、あいまいさを避けるためにエスケープが本当に必要です。

おそらく、エスケープしたい文字列が、エスケープする必要がある二重引用符を(不確実性なしに)認識できる本当に特殊な構造を持っている場合、独自の自動エスケープ手順を作成できますが、ゼロから始める必要があります。何も組み込まれていません。

于 2014-10-07T21:40:23.727 に答える