TypeError:使用Python解析JSON时字符串索引必须是整数?
我现在不明白为什么我不能解析这个JSON字符串。类似的代码在其他JSON字符串上运行良好,但在这个字符串上不行——我正在尝试解析JSON字符串并从JSON中提取脚本 下面是我的代码TypeError:使用Python解析JSON时字符串索引必须是整数?,python,json,parsing,Python,Json,Parsing,我现在不明白为什么我不能解析这个JSON字符串。类似的代码在其他JSON字符串上运行良好,但在这个字符串上不行——我正在尝试解析JSON字符串并从JSON中提取脚本 下面是我的代码 for step in steps: step_path = '/example/v1' +'/'+step data, stat = zk.get(step_path) jsonStr = data.decode("utf-8") print(jsonStr) j = js
for step in steps:
step_path = '/example/v1' +'/'+step
data, stat = zk.get(step_path)
jsonStr = data.decode("utf-8")
print(jsonStr)
j = json.loads(json.dumps(jsonStr))
print(j)
shell_script = j['script']
print(shell_script)
因此,第一个print(jsonStr)
将打印出如下内容-
{"script":"#!/bin/bash\necho Hello world1\n"}
{"script":"#!/bin/bash\necho Hello world1\n"}
第二个print(j)
将打印出如下内容-
{"script":"#!/bin/bash\necho Hello world1\n"}
{"script":"#!/bin/bash\necho Hello world1\n"}
然后第三次打印没有打印出来,它给出了这个错误-
Traceback (most recent call last):
File "test5.py", line 33, in <module>
shell_script = j['script']
TypeError: string indices must be integers
回溯(最近一次呼叫最后一次):
文件“test5.py”,第33行,在
shell_script=j['script']
TypeError:字符串索引必须是整数
所以我想知道我到底做错了什么
我使用了上面相同的代码来解析JSON,效果很好。尝试将
j=JSON.loads(JSON.dumps(jsonStr))
替换为j=JSON.loads(jsonStr)
问题是jsonStr是一个用JSON编码某些对象的字符串,而不是实际对象
很明显,您知道它是一个字符串,因为您称它为jsonStr
。事实证明,这条线是有效的:
jsonStr = data.decode("utf-8")
因此,jsonStr
是一个字符串。对字符串调用json.dumps
是完全合法的。不管该字符串是某个对象的JSON编码,还是您的姓氏;可以用JSON对该字符串进行编码。然后你可以解码这个字符串,找回原来的字符串
那么这个,
j = json.loads(json.dumps(jsonStr))
…将返回与j
中的jsonStr
完全相同的字符串。你还没有解码到原始对象
要做到这一点,请不要进行额外的编码:
j = json.loads(jsonStr)
如果不清楚,请尝试在交互式终端上使用它:
>>> obj = ['abc', {'a': 1, 'b': 2}]
>>> type(obj)
list
>>> obj[1]['b']
2
>>> j = json.dumps(obj)
>>> type(j)
str
>>> j[1]['b']
TypeError: string indices must be integers
>>> jj = json.dumps(j)
>>> type(jj)
str
>>> j
'["abc", {"a": 1, "b": 2}]'
>>> jj
'"[\\"abc\\", {\\"a\\": 1, \\"b\\": 2}]"'
>>> json.loads(j)
['abc', {'a': 1, 'b': 2}]
>>> json.loads(j) == obj
True
>>> json.loads(jj)
'["abc", {"a": 1, "b": 2}]'
>>> json.loads(jj) == j
True
>>> json.loads(jj) == obj
False
好的。。。因此,对于那些因为习惯了JS而仍然迷路的人来说,这就是我在测试了多个用例后所理解的:
不会使字符串准备好加载json.dumps
。它只会将其编码为JSON规范(通过在几乎所有地方添加转义)json.loads
会将格式正确的json字符串转换为python字典。只有当JSON遵循JSON规范(没有单引号,布尔值的第一个字母大写,等等)时,它才会起作用json.load
$ obj = {"foobar": True}
这不是json!这是一个使用python类型(如布尔型)的python字典
True
与JSON规范不兼容,因此为了将其发送到API,您必须将其序列化为REALJSON。这就是json.dumps
的用武之地
$ json.dumps({"foobar": True})
'{"foobar": true}'
看到了吗True
变成了True
,这是真正的JSON。您现在有了一个可以发送到现实世界的字符串。干得好
加载JSON——解码故事
现在让我们来讨论一下json.loads
您有一个看起来像json的字符串,但它只是一个字符串,您需要的是一个python字典。让我们浏览以下示例:
$ string = '{"foobar": true}'
$ dict = json.loads(string)
{'foobar': True}
这里有一个类似于JSON的字符串。您可以使用json.loads
在字典中转换此字符串,并执行dict[“foobar”]
操作,该操作将返回True
那么,为什么会有这么多错误呢
好的,如果您的JSON看起来像JSON,但实际上与JSON不兼容(按规范),例如:
$ string = "{'foobar': true}"
$ json.loads(string)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
砰!这不起作用,因为JSON规范不允许使用单引号,而只允许使用双引号。。。
如果将引号反转为'{“foobar”:true}'
,则它将起作用
您可能尝试过的是:
string = json.loads(json.dumps("{'foobar': true}"))
此JSON无效(请检查引号),而且您将得到一个字符串作为结果。什么?我知道
将修复json字符串,但也将对其进行编码。编码将使json.dumps
无效,即使json现在可以使用了json.loads
json.dumps
编码和json.loads
解码强>
所以你在这里做的是编码一个字符串,然后解码这个字符串。但它仍然是一根绳子!你没有做任何事情来改变这个事实!如果您想将它从字符串转换到字典,则需要额外的步骤…=>第二次json。加载强>
让我们用一个有效的JSON(没有单引号)来尝试
json字符串经过json.dumps
并被编码。然后它通过json.loads
在解码的地方加载(无用的…是的)。最后,它再次通过json.loads
,并从字符串转换为字典。如您所见,在这种情况下,使用json.dumps
只会添加一个无用的步骤
最后一件事。如果我们再次使用错误的JSON执行相同的操作:
$ string = json.loads(json.loads(json.dumps("{'foobar': true}")))
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
这里的引语是错误的(你现在还不习惯吗?)。
这里发生的是json.dumps
修复了jsonjson.loads
删除了修复(lol),最后json.loads
得到了错误的json,由于前两个步骤相互取消,json没有改变
TL;博士
总之:
自己修好!不要将json.loads
格式错误的json交给json.loads
和json.dumps混用,以修复只有您才能修复的内容。
希望这对某人有所帮助;-)
免责声明。我不是python专家。
请在评论部分质疑这个答案。第三次的预期输出是什么?它应该从JSON字符串中提取脚本部分。。所以它应该打印出#/bin/bash\necho Hello world1\n
。对吗?可能j
与jsonStr
相同,是一个字符串。使用字符串键对其进行索引失败,出现您描述的异常。省略dumps
调用会使loads
调用将原始字符串转换为字典,而