AKI*_*WEB 21 python parsing json
我现在很困惑为什么我无法解析这个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)
Run Code Online (Sandbox Code Playgroud)
所以第一个print(jsonStr)
会打印出这样的东西 -
{"script":"#!/bin/bash\necho Hello world1\n"}
Run Code Online (Sandbox Code Playgroud)
第二个print(j)
会打印出这样的东西 -
{"script":"#!/bin/bash\necho Hello world1\n"}
Run Code Online (Sandbox Code Playgroud)
然后第三次打印没有打印出来,它给出了这个错误 -
Traceback (most recent call last):
File "test5.py", line 33, in <module>
shell_script = j['script']
TypeError: string indices must be integers
Run Code Online (Sandbox Code Playgroud)
所以我想知道我在这里做错了什么?
我使用相同的上面的代码来解析JSON,它工作正常..
aba*_*ert 33
问题是jsonStr是一个字符串,它编码JSON中的某个对象,而不是实际的对象.
你显然知道它是一个字符串,因为你打电话给它jsonStr
.事实证明,这条生产线的工作原理是:
jsonStr = data.decode("utf-8")
Run Code Online (Sandbox Code Playgroud)
所以,jsonStr
是一个字符串.调用json.dumps
字符串是完全合法的.该字符串是否是某个对象的JSON编码或您的姓氏并不重要; 你可以用JSON编码该字符串.然后你可以解码该字符串,获取原始字符串.
所以这:
j = json.loads(json.dumps(jsonStr))
Run Code Online (Sandbox Code Playgroud)
......是想给你回完全相同的字符串jsonStr
在j
.你仍然没有解码到原始对象.
要做到这一点,只是不要做额外的编码:
j = json.loads(jsonStr)
Run Code Online (Sandbox Code Playgroud)
如果不清楚,请尝试使用交互式终端:
>>> 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
Run Code Online (Sandbox Code Playgroud)
1st*_*st1 21
尝试更换j = json.loads(json.dumps(jsonStr))
用j = json.loads(jsonStr)
.
Doc*_*tor 10
好吧...所以对于那些因为习惯了 JS 而仍然迷失方向的人来说,这是我在测试了多个用例后所理解的:
json.dumps
不会使您的字符串准备好加载json.loads
。它只会将其编码为 JSON 规范(通过在几乎所有地方添加转义符)!
json.loads
会将格式正确的 JSON 字符串转换为 Python 字典。仅当 JSON 遵循 JSON 规范(无单引号、布尔值的第一个字母大写等)时,它才有效。
让我们举个例子!
$ obj = {"foobar": True}
Run Code Online (Sandbox Code Playgroud)
这不是 json !这是一个使用 python 类型(如布尔值)的 python 字典。
True
与 JSON 规范不兼容,因此为了将其发送到 API,您必须将其序列化为REAL JSON。这就是json.dumps
进来的地方!
$ json.dumps({"foobar": True})
'{"foobar": true}'
Run Code Online (Sandbox Code Playgroud)
看 ?True
变成了true
真正的 JSON。您现在有了一个可以发送到现实世界的字符串。好工作。
那么现在我们来谈谈json.loads
。
你有一个看起来像 json 的字符串,但它只是一个字符串,你想要的是一个 python 字典。让我们看一下以下示例:
$ string = '{"foobar": true}'
$ dict = json.loads(string)
{'foobar': True}
Run Code Online (Sandbox Code Playgroud)
这里我们有一个看起来像 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
Run Code Online (Sandbox Code Playgroud)
嘭!这是行不通的,因为 JSON 规范不允许你使用单引号,而只允许使用双引号...如果你反转引号,那么'{"foobar": true}'
它就会工作。
您可能尝试过的是:
string = json.loads(json.dumps("{'foobar': true}"))
Run Code Online (Sandbox Code Playgroud)
此 JSON 无效(检查引号),而且您将得到一个字符串作为结果。失望吗?我知道...
json.dumps
将修复您的 JSON 字符串,但也会对其进行编码。json.loads
即使 JSON 现在可以使用,编码也会变得毫无用处。你必须了解json.dumps
编码和json.loads
解码!
因此,您在这里所做的就是对字符串进行编码,然后对字符串进行解码。但它仍然是一个字符串!你没有做任何事情来改变这个事实!如果你想将它从字符串获取到字典,那么你需要一个额外的步骤... =>第二步json.loads
!
让我们尝试使用有效的 JSON(不是单引号)
$ obj = json.loads(json.loads(json.dumps('{"foobar": true}')))
$ obj["foobar"]
True
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
这里的引号是错误的(你现在还没习惯吗?)。这里发生的事情json.dumps
修复了你的 JSON。json.loads
删除了修复程序(笑),最终json.loads
得到了错误的 JSON,该 JSON 没有改变,因为前 2 个步骤相互抵消了。
结论:自己修复 JSON!不要使用json.loads
格式错误的 JSON,也不要尝试混合json.loads
来json.dumps
修复只有您可以修复的内容。
希望这对某人有帮助;-)
免责声明。我不是Python专家。
欢迎在评论部分质疑这个答案。