TypeError:使用Python解析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

我现在不明白为什么我不能解析这个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 = 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.loads
    。它只会将其编码为JSON规范(通过在几乎所有地方添加转义)

  • json.load
    会将格式正确的json字符串转换为python字典。只有当JSON遵循JSON规范(没有单引号,布尔值的第一个字母大写,等等)时,它才会起作用

转储JSON—一个编码故事 让我们举个例子吧

$ 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.dumps
    将修复json字符串,但也将对其进行编码。编码将使
    json.loads
    无效,即使json现在可以使用了
您必须了解
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
修复了json
json.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
调用将原始字符串转换为字典,而