Python 无法分析JSON文件中的选项卡

Python 无法分析JSON文件中的选项卡,python,json,Python,Json,加载JSON文件时,我遇到了一个解析问题,这些文件中似乎包含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文件时,我遇到了一个解析问题,这些文件中似乎包含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
或空格替换选项卡吗?还是我在这里遗漏了什么

更新: 下面是
simplejson
中的一个问题示例:

foo = '{"My_string": "Foo bar.\t Bar foo."}'
simplejson.loads(foo)

JSONDecodeError: Invalid control character '\t' at: line 1 column 24 (char 23)

制表符在值之外划界空白是合法的,但不在字符串之内。改用
\t

编辑:根据您的评论,我对选项卡的实际含义感到困惑。。 制表符只是一个普通字符,如“a”或“5”或“.”或通过按键盘上的键输入的任何其他字符。它占用一个字节,其数值为9。没有反斜杠或小写字母“t”

将制表符与“a”或“5”或“.”区别开来的是,作为一个使用眼球的人,您通常无法查看文本显示并识别或计数制表符字符。从视觉上看,制表符序列与(通常较大但视觉上不确定数量的)空间序列相同

为了在计算机处理的文本中清晰地表示制表符,我们有各种语法方法来表示“嘿,某个软件!稍后用制表符替换这个垃圾,好吗?”

在编程语言的历史上,有两种主要的方法;如果回到20世纪50年代,两种方法并存,两种最古老的高级语言各有一种。Lisp对字符文本进行了命名,如
#\Tab
;一旦从程序源中读取它们,它们就被转换。Fortran只有
CHAR
函数,该函数在运行时被调用,并返回与参数匹配的字符:
CHAR(9)
返回一个制表符。(当然,如果它真的是
CHAR(9)
而不是
CHAR(
某个表达式的结果是9
,那么优化编译器可能会注意到这一点,并在编译时用一个选项卡替换函数调用,把我们放回另一阵营。)

通常,对于这两种解决方案类型,如果您想将特殊字符粘贴到更大的字符串中,您必须自己进行连接;例如,一个80年代的儿童黑客基础可能会写这样的东西:

10 PRINT "This is a tab ->"; CHR$(9); "<- That was a tab"
不是有效的JSON。Python解释器在读取字符串时立即将
\t
序列转换为实际的制表符-远远早于JSON处理器看到它

通过将反斜杠加倍,可以告诉Python在字符串中放入一个文本
\t
,而不是制表符:

foo = '{"My_string": "Foo bar.\\t Bar foo."}'
或者您可以使用“原始”字符串语法,它根本不解释特殊的反斜杠序列:

foo = r'{"My_string": "Foo bar.\t Bar foo."}'
无论哪种方式,JSON处理器都会看到一个包含反斜杠后跟“t”的字符串,而不是一个包含制表符的字符串。

您可以通过转义将制表符包含在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)
>>json.loads(“{”我的字符串“:“Foo\tBar”}”)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/_init__.py”,第338行,加载
返回\u默认\u解码器。解码
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py”,解码中的第365行
obj,end=self.raw\u decode(s,idx=\u w(s,0.end())
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py”,第381行,原始解码
obj,end=self.scan_一次(s,idx)
ValueError:第1行第19列(字符18)处的控制字符无效
来自:

允许在任何标记之前或之后使用不重要的空格。这个 空白字符是:字符制表(U+0009),换行 (U+000A)、回车符(U+000D)和空格(U+0020)。空白是 在任何令牌中都不允许,但在 字符串

这意味着JSON字符串中不允许使用文本制表符。您需要将其转义为
\t

此外,如果在Python字符串文本中提供json文本,则需要双转义该选项卡:

foo = '{"My_string": "Foo bar.\\t Bar foo."}' # in a Python source
或者使用Python原始字符串文字:

printf("This is a tab -> *t <- That was a tab");
foo = r'{"My_string": "Foo bar.\t Bar foo."}' # in a Python source

请分享我的经验:


我正在使用snakemake和一个用Json编写的配置文件。json文件中有用于缩进的选项卡。TAB为此目的是合法的。但我收到错误消息:snakemake.exceptions.WorkflowError:Config文件不是有效的JSON或YAML。我相信这是一只蛇虫子;但我可能错了。请评论。将所有选项卡替换为空格后,错误消息消失。

在节点红色流i中,遇到相同类型的问题:

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"');

嗯,很有趣。用
\t
替换有问题的
选项卡
会使JSONlint验证器在线通过,但是
simplejson
抱怨:
JSONDecodeError:第XXX行第YYY列(char ZZZ)处的无效控制字符“\t”
JSONDecodeError具有误导性。它发现一个无效的文本制表符。为了显示错误消息,将其转换为“\t”,而不是在屏幕上显示文字选项卡。谢谢
mtitan8
。你知道官方JSON规范中是否提到/讨论过这个问题吗?或者它是特定于librari
{ "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" }  
 flow.set("delimiter",'"\\t"');