无法解析JSON文件中的TAB

Jos*_*osh 30 python json

在加载似乎具有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文本的复制/粘贴.

我曾尝试加载该文件,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)
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)

  • @Josh:读完整句:*"除了字符串中允许空格"*. (7认同)
  • 天啊,明白了.谢谢! (2认同)

Mar*_*eed 7

选项卡是合法的,可以在值之外分隔空格,但不在字符串内.请\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'的字符串,而不是包含制表符的字符串.

  • JSONDecodeError具有误导性.它找到了一个无效的文字制表符.为了显示错误消息,它转换为'\ t'而不是在屏幕上显示文字选项卡. (2认同)

mdm*_*dml 5

您可以包括标签通过逃避他们在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)

  • 乔希,你的问题暗示有问题,但没有。如果您使用简单的“\t”,那么 Python 会将其解释为文字制表符,这在 JSON 值中无效。所以你将它转义为“\\t”,这会导致 Python 值“\t”,它是有效的 JSON。有效字符在 http://www.json.org/ 的右侧 (3认同)