无法解析JSON文件中的TAB

时间:2013-11-05 21:09:06

标签: python json

在加载似乎包含 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文本的复制/粘贴。

我尝试使用jsonsimplejson加载此文件但未成功。我怎样才能正确加载?我应该预处理文件并用\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)

5 个答案:

答案 0 :(得分:35)

来自JSON standard

  

任何令牌之前或之后都允许使用无关紧要的空格。该   空白字符是:字符制表(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"');