在加载似乎包含 TAB 字符的JSON文件时,我遇到了解析问题。
当我转到http://jsonlint.com/时,我输入了带有TAB字符的部分:
{
"My_String": "Foo bar. Bar foo."
}
验证人抱怨:
Parse error on line 2:
{ "My_String": "Foo bar. Bar foo."
------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['
这实际上是违规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)
答案 0 :(得分:35)
任何令牌之前或之后都允许使用无关紧要的空格。该 空白字符是:字符制表(U + 0009),换行 (U + 000A),回车(U + 000D)和空格(U + 0020)。空白是 不允许在任何令牌内,但允许的空间除外 字符串。
这意味着JSON字符串中不允许使用文字制表符。您需要将其转义为\t
(in a .json-file):
{"My_string": "Foo bar.\t Bar foo."}
此外,如果在Python字符串文字中提供了json文本,那么您需要双重转义选项卡:
foo = '{"My_string": "Foo bar.\\t Bar foo."}' # in a Python source
或者使用Python原始字符串文字:
foo = r'{"My_string": "Foo bar.\t Bar foo."}' # in a Python source
答案 1 :(得分:7)
选项卡是合法的,可以在值之外分隔空格,但不在字符串中。请改用\t
。
编辑:根据您的评论,我看到一些关于标签实际上是什么的混淆。 制表符只是一个普通字符,如'a'或'5'或'。'或者通过按键盘上的键输入的任何其他字符。它占用一个字节,其数值为9.没有反斜杠或小写't'。
什么将标签放在与“a”或“5”或“。”不同的类别中。事实上,作为一个使用你的眼球的人,你通常无法查看文本的显示并识别或计算制表符。在视觉上,一系列标签与一系列(通常较大但仍然在视觉上不确定的数量)空间相同。
为了明确地表示用于计算机处理的文本中的标签,我们有各种句法方法来说“嘿,某些软件!稍后用标签字符替换这个垃圾,好吗?” 。
在编程语言的历史中,有两种主要方法;如果你回到20世纪50年代,你可以将两种方法并排存在,两种最古老的高级语言中的一种。 Lisp命名了像#\Tab
这样的字符文字;一旦从程序源读取它们就会被转换。 Fortran只有CHAR
函数,它在运行时调用并返回与参数匹配的字符:CHAR(9)
返回一个选项卡。 (当然,如果真的是CHAR(9)
而不是CHAR(
某个表达式可以解决9 )
,那么优化编译器可能会注意到并替换该函数在编译时用标签调用,让我们回到另一个阵营。)
通常,对于两种解决方案类型,如果要将特殊字符粘贴到较大的字符串中,则必须自己进行连接;例如,一个在80年代攻击BASIC的孩子可能写下这样的东西:
10 PRINT "This is a tab ->"; CHR$(9); "<- That was a tab"
但有些语言 - 最着名的是以B语言开头的家族 - 引入了将这些字符直接包含在字符串文字中的能力:
printf("This is a tab -> *t <- That was a tab");
BCPL保留了*
语法,但是系列中的下一个语言C用反斜杠替换它,可能是因为它们需要比文字反斜杠读取和写入文字星号更多。
无论如何,包括Python和Javascript在内的许多语言都借用或继承了C的约定。因此,在两种语言中,两个表达式"\t"
和'\t'
各自产生一个字符的字符串,其中一个字符是制表符。
JSON基于Javascript的语法,但它只允许其受限制的子集。例如,字符串必须用双引号("
)而不是单引号('
)括起来,并且不允许使用文字制表符。
这意味着您的更新中的此Python字符串:
foo = '{"My_string": "Foo bar.\t Bar foo."}'
是无效的JSON。 Python解释器在读取字符串时将\t
序列转换为实际的制表符 - 早在JSON处理器看到它之前。
你可以通过加倍反斜杠告诉Python在字符串中放置文字\t
而不是制表符:
foo = '{"My_string": "Foo bar.\\t Bar foo."}'
或者你可以使用“raw”字符串语法,它根本不解释特殊的反斜杠序列:
foo = r'{"My_string": "Foo bar.\t Bar foo."}'
无论哪种方式,JSON处理器都会看到一个包含反斜杠后跟't'的字符串,而不是包含选项卡的字符串。
答案 2 :(得分:4)
您可以通过转义它们在JSON文件中的值(而不是空格)中包含标签。这是Python2.7中json
模块的一个工作示例:
>>> import json
>>> obj = json.loads('{"MY_STRING": "Foo\\tBar"}')
>>> obj['MY_STRING']
u'Foo\tBar'
>>> print obj['MY_STRING']
Foo Bar
虽然没有转义'\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)
答案 3 :(得分:0)
只是为了分享我的经验:
我正在使用snakemake和用Json编写的配置文件。 json文件中有用于缩进的选项卡。 TAB是合法的。但我收到错误消息:snakemake.exceptions.WorkflowError:配置文件无效JSON或YAML。我相信这是一个蛇怪的错误;但我可能是错的。请评论。用空格替换所有TAB后,错误消息就消失了。
答案 4 :(得分:0)
在节点红色流程中,我面临同样类型的问题:
flow.set("delimiter",'"\t"');
错误:
{ "status": "ERROR", "result": "Cannot parse config: String: 1: in value for key 'delimiter': JSON does not allow unescaped tab in quoted strings, use a backslash escape" }
<强>溶液强>
我在代码中添加\\t
。
flow.set("delimiter",'"\\t"');