[英]TypeError: string indices must be integers while parsing JSON using Python?
I am confuse now why I am not able to parse this JSON string.我现在很困惑为什么我无法解析这个 JSON 字符串。 Similar code works fine on other JSON string but not on this one - I am trying to parse JSON String and extract script from the JSON.
类似的代码适用于其他 JSON 字符串,但不适用于这个字符串 - 我正在尝试解析 JSON 字符串并从 JSON 中提取脚本。
Below is my code.下面是我的代码。
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)
So the first print(jsonStr)
will print out something like this -所以第一个
print(jsonStr)
会打印出这样的东西 -
{"script":"#!/bin/bash\necho Hello world1\n"}
And the second print(j)
will print out something like this -第二个
print(j)
将打印出这样的东西 -
{"script":"#!/bin/bash\necho Hello world1\n"}
And then the third print doesn't gets printed out and it gives this error -然后第三次打印没有打印出来,它给出了这个错误 -
Traceback (most recent call last):
File "test5.py", line 33, in <module>
shell_script = j['script']
TypeError: string indices must be integers
So I am wondering what wrong I am doing here?所以我想知道我在这里做错了什么?
I have used same above code to parse the JSON and it works fine..我使用上面相同的代码来解析 JSON,它工作正常..
The problem is that jsonStr is a string that encodes some object in JSON, not the actual object.问题是 jsonStr 是一个字符串,它用 JSON 对某个对象进行编码,而不是实际的对象。
You obviously knew it was a string, because you called it jsonStr
.您显然知道它是一个字符串,因为您将其称为
jsonStr
。 And it's proven by the fact that this line works:这条线有效的事实证明了这一点:
jsonStr = data.decode("utf-8")
So, jsonStr
is a string.所以,
jsonStr
是一个字符串。 Calling json.dumps
on a string is perfectly legal.在字符串上调用
json.dumps
是完全合法的。 It doesn't matter whether that string was the JSON encoding of some object, or your last name;该字符串是某个对象的 JSON 编码还是您的姓氏并不重要; you can encode that string in JSON.
您可以在 JSON 中对该字符串进行编码。 And then you can decode that string, getting back the original string.
然后您可以解码该字符串,取回原始字符串。
So, this:所以,这个:
j = json.loads(json.dumps(jsonStr))
… is going to give you back the exact same string as jsonStr
in j
. ... 将返回与
j
jsonStr
完全相同的字符串。 Which you still haven't decoded to the original object.您还没有解码为原始对象。
To do that, just don't do the extra encode:要做到这一点,不要做额外的编码:
j = json.loads(jsonStr)
If that isn't clear, try playing with it an interactive terminal:如果还不清楚,请尝试在交互式终端上使用它:
>>> 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
尝试用j = json.loads(json.dumps(jsonStr))
替换j = json.loads(json.dumps(jsonStr))
j = json.loads(jsonStr)
。
Ok... So for people who are still lost because they are used to JS this is what I understood after having tested multiple use cases :好吧...所以对于那些仍然迷路的人,因为他们已经习惯了 JS,这是我在测试了多个用例后的理解:
json.dumps
does not make your string ready to be loaded with json.loads
. json.dumps
不会让您的字符串准备好加载json.loads
。 It will only encode it to JSON specs (by adding escapes pretty much everywhere) !它只会将其编码为 JSON 规范(通过在几乎所有地方添加转义符)!
json.loads
will transform a correctly formatted JSON string to a python dictionary. json.loads
会将格式正确的 JSON 字符串转换为 Python 字典。 It will only work if the JSON follows the JSON specs (no single quotes, uppercase for boolean's first letter, etc).只有当 JSON 遵循 JSON 规范(没有单引号,布尔值的首字母大写等)时,它才会起作用。
Lets take an example !让我们举个例子!
$ obj = {"foobar": True}
This is NOT json !这不是 json ! This is a python dictionary that uses python types (like booleans).
这是一个使用 python 类型(如布尔值)的 python 字典。
True
is not compatible with the JSON specs so in order to send this to an API you would have to serialize it to REAL JSON. True
与 JSON 规范不兼容,因此为了将其发送到 API,您必须将其序列化为REAL JSON。 That's where json.dumps
comes in !这就是
json.dumps
用武之地!
$ json.dumps({"foobar": True})
'{"foobar": true}'
See ?看到了吗?
True
became true
which is real JSON. True
变为true
,这是真正的 JSON。 You now have a string that you can send to the real world.您现在有一个可以发送到现实世界的字符串。 Good job.
干得好。
So now lets talk about json.loads
.所以现在让我们谈谈
json.loads
。
You have a string that looks like json but its only a string and what you want is a python dictionary.你有一个看起来像 json 的字符串,但它只是一个字符串,你想要的是一个 python 字典。 Lets walk through the following examples :
让我们来看看下面的例子:
$ string = '{"foobar": true}'
$ dict = json.loads(string)
{'foobar': True}
Here we have a string that looks like JSON.这里我们有一个看起来像 JSON 的字符串。 You can use
json.loads
to transform this string in dictionary and do dict["foobar"]
which will return True
.您可以使用
json.loads
在字典中转换此字符串并执行dict["foobar"]
这将返回True
。
So, why so many errors ?那么,为什么会有这么多错误呢?
Well, if your JSON looks like JSON but is not really JSON compatible (spec wise), for instance :好吧,如果您的 JSON 看起来像 JSON,但实际上并不兼容 JSON(规范方面),例如:
$ string = "{'foobar': true}"
$ json.loads(string)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
BAM !砰! This is not working because JSON specs wont allow you to have single quotes but only double ones... If you reverse the quotes to
'{"foobar": true}'
then it will work.这是行不通的,因为 JSON 规范不允许您使用单引号,而只允许使用双引号...如果您将引号反转为
'{"foobar": true}'
那么它将起作用。
What you probably have tried is :您可能尝试过的是:
string = json.loads(json.dumps("{'foobar': true}"))
This JSON is invalid (check the quotes) and moreover you'll get a string as a results.这个 JSON 是无效的(检查引号),而且你会得到一个字符串作为结果。 Disapointed ?
失望? I know...
我知道...
json.dumps
WILL fix you JSON string but will also encode it. json.dumps
将修复您的 JSON 字符串,但也会对其进行编码。 The encoding will render json.loads
useless even if the JSON is now good to go.json.loads
无用。 You have to understand that json.dumps
encodes and json.loads
decodes !您必须了解
json.dumps
编码和json.loads
解码!
So what you did here is encode a string and then decode the string.所以你在这里做的是编码一个字符串,然后解码这个字符串。 But its still a string !
但它仍然是一个字符串! you haven't done anything to change that fact !
你没有做任何事情来改变这个事实! If you want to get it from string to dictionary then you need an extra step... => A second
json.loads
!如果您想将它从字符串转换为字典,那么您需要一个额外的步骤... =>第二个
json.loads
!
Lets try that with a valid JSON (no mean single quotes)让我们尝试使用有效的 JSON(不是单引号)
$ obj = json.loads(json.loads(json.dumps('{"foobar": true}')))
$ obj["foobar"]
True
The json string went through json.dumps
and got encoded. json 字符串通过
json.dumps
并被编码。 Then it when through json.loads
where it got decoded (useless...YEAY).然后当它通过
json.loads
解码时(没用......是的)。 Finaly, it went through json.loads
AGAIN and got transformed from string to dictionary.最后,它再次通过
json.loads
并从字符串转换为字典。 As you can see, using json.dumps
only adds a useless step in that situation.如您所见,在这种情况下,使用
json.dumps
只会增加一个无用的步骤。
One last thing.最后一件事。 If we do the same thing again but with a bad JSON:
如果我们再次执行相同的操作,但 JSON 错误:
$ string = json.loads(json.loads(json.dumps("{'foobar': true}")))
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
Quotes are wrong here (ain't you getting used to this by now ?).这里的引用是错误的(你现在还不习惯吗?)。 What happend here is that
json.dumps
fixed your JSON.这里发生的事情是
json.dumps
修复了你的 JSON。 json.loads
removed the fix (lol) and finaly json.loads
got the bad JSON which did not change as the first 2 steps canceled each other. json.loads
删除了修复 (lol),最后json.loads
得到了错误的 JSON,它没有改变,因为前两个步骤相互取消。
In conclusion : Fix you JSON yourself !总之:自己修复 JSON! Don't give to
json.loads
wrongly formated JSON and don't try to mix json.loads
with json.dumps
to fix what only you can fix.不要给
json.loads
格式错误的 JSON,也不要尝试将json.loads
与json.dumps
混合来修复只有你能修复的东西。
Hope this helped someone ;-)希望这对某人有所帮助;-)
Disclaimer.免责声明。 I'm no python expert.
我不是python专家。
Feel free to challenge this answer in the comment section.随时在评论部分挑战这个答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.