在加载似乎具有TAB字符的JSON文件时,我遇到了解析问题.
当我访问http://jsonlint.com/时,我输入了带有TAB字符的部分:
{
"My_String": "Foo bar. Bar foo."
}
Run Code Online (Sandbox Code Playgroud)
验证人抱怨:
Parse error on line 2:
{ "My_String": "Foo bar. Bar foo."
------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['
Run Code Online (Sandbox Code Playgroud)
这实际上是违规JSON文本的复制/粘贴.
我曾尝试加载该文件,json并simplejson没有成功.我怎样才能正确加载?我应该只是预处理文件并用\t空格替换TAB 吗?或者我在这里缺少什么?
这也是一个有问题的例子simplejson:
foo = '{"My_string": "Foo bar.\t Bar foo."}'
simplejson.loads(foo)
JSONDecodeError: Invalid control character '\t' at: line 1 column 24 (char 23)
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 37
来自JSON标准:
在任何令牌之前或之后允许无关紧要的空格.空白字符为:字符列表(U + 0009),换行符(U + 000A),回车符(U + 000D)和空格(U + 0020).除了字符串中允许使用空格外,任何标记中都不允许使用空格.
这意味着JSON字符串中不允许使用文字制表符.你需要将其转义为\t (在.json文件中):
{"My_string": "Foo bar.\t Bar foo."}
Run Code Online (Sandbox Code Playgroud)
另外如果在Python字符串文字中提供了json文本,那么你需要双重转义选项卡:
foo = '{"My_string": "Foo bar.\\t Bar foo."}' # in a Python source
Run Code Online (Sandbox Code Playgroud)
或者使用Python原始字符串文字:
foo = r'{"My_string": "Foo bar.\t Bar foo."}' # in a Python source
Run Code Online (Sandbox Code Playgroud)
选项卡是合法的,可以在值之外分隔空格,但不在字符串内.请\t改用.
编辑:根据你的评论,我看到一些关于标签实际是什么的混淆..标签字符只是一个普通字符,如'a'或'5'或'.' 或者通过按键盘上的键输入的任何其他字符.它占用一个字节,其数值为9.没有反斜杠或小写't'.
什么将标签放在与"a"或"5"或"."不同的类别中.事实上,作为一个使用你的眼球的人,你通常不能查看文本的显示并识别或计算制表符.在视觉上,一系列标签与(通常更大但仍然在视觉上不确定数量)空间的序列相同.
为了明确地表示用于计算机处理的文本中的选项卡,我们有各种句法方法来说"嘿,某些软件!稍后用标签字符替换这个垃圾,好吗?".
在编程语言的历史中,有两种主要方法; 如果你回到1950年,你会得到通过双方的接近现有的一侧,一个在每两个最古老的高级语言.Lisp已将字符文字命名为#\Tab; 一旦从程序源读取它们就会被转换.Fortran只有CHAR函数,它在运行时调用并返回与参数匹配的字符:CHAR(9)返回一个选项卡.(当然,如果它真的CHAR(9)并且不是CHAR(某个表达式可以达到9),那么优化编译器可能会注意到并在编译时用制表符替换函数调用,将我们重新放回另一个阵营.)
一般来说,对于两种解决方案类型,如果您想将特殊字符粘贴在较大的字符串中,则必须自己进行连接; 例如,一个80年代攻击BASIC的孩子可能写下这样的东西:
10 PRINT "This is a tab ->"; CHR$(9); "<- That was a tab"
Run Code Online (Sandbox Code Playgroud)
但是有些语言 - 最着名的是以B语言开头的家族 - 引入了将这些字符直接包含在字符串文字中的能力:
printf("This is a tab -> *t <- That was a tab");
Run Code Online (Sandbox Code Playgroud)
BCPL保留了*语法,但是系列中的下一个语言C用反斜杠替换它,可能是因为它们需要比文字反斜杠更频繁地读写文字星号.
无论如何,包括Python和Javascript在内的许多语言都借用或继承了C的约定.因此,在这两种语言,两人的表情"\t"和'\t'每个结果在一个字符串,其中一个字符是一个标签.
JSON基于Javascript的语法,但它只允许其受限制的子集.例如,字符串必须用双引号(")而不是单个(')括起来,并且不允许使用文字制表符.
这意味着您的更新中的这个Python字符串:
foo = '{"My_string": "Foo bar.\t Bar foo."}'
Run Code Online (Sandbox Code Playgroud)
是无效的JSON.Python解释器在\t读取字符串时将序列转换为实际的制表符 - 早在JSON处理器看到它之前.
您可以\t通过将反斜杠加倍来告诉Python将字符串放入字符串而不是制表符:
foo = '{"My_string": "Foo bar.\\t Bar foo."}'
Run Code Online (Sandbox Code Playgroud)
或者您可以使用"原始"字符串语法,它根本不解释特殊的反斜杠序列:
foo = r'{"My_string": "Foo bar.\t Bar foo."}'
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,JSON处理器都会看到一个包含反斜杠后跟't'的字符串,而不是包含制表符的字符串.
您可以包括标签内通过逃避他们在JSON文件中的值(而不是为空白)。这是jsonPython2.7 中模块的工作示例:
>>> import json
>>> obj = json.loads('{"MY_STRING": "Foo\\tBar"}')
>>> obj['MY_STRING']
u'Foo\tBar'
>>> print obj['MY_STRING']
Foo Bar
Run Code Online (Sandbox Code Playgroud)
虽然没有逃避'\t'导致错误:
>>> json.loads('{"MY_STRING": "Foo\tBar"}')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 381, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Invalid control character at: line 1 column 19 (char 18)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24246 次 |
| 最近记录: |