json.loads 不能把某文本的 str 转换字典类型,复制该 str 到 py 文件内即可转换字典类型,什么原因?

2021-05-05 21:38:57 +08:00
 ALLROBOT
很奇怪的问题,stream_header.txt 文本如下

{"appId":"amp-ios-10000","accessToken":"xxxxxxxxxxxxxxx","User-Agent":"Mozilla/5.0","Content-Type":"application/json;charset=UTF-8","Host":"messageapi.campusphere.net","Accept-Encoding":"gzip"}

我通过 with 函数读取文本,转成字典类型的值赋予某变量
with open("stream_header.txt","r")as header_:
header=json.loads(dumps(header_.read()))
print(type(header))
# 读取上一个时间戳
with open("old_identity_information.txt", "r")as old:
date =json.loads(dumps(old.read()))

模拟发送数据包的时候,弹出 AttributeError: 'str' object has no attribute 'items'错误,提示 str 无法通过字典方式提取某 key 值
经过检查是 json.loads 的问题,加了 print(type(header)),编辑器提示<class 'str'>,另一个 date 也提示是 str 类型。。

str 复制到 py,写成这样:

d='{"appId":"amp-ios-10000","accessToken":"xxxxxxxxxxxxxxx","User-Agent":"Mozilla/5.0","Content-Type":"application/json;charset=UTF-8","Host":"messageapi.campusphere.net","Accept-Encoding":"gzip"}'
d=loads(d)
print(type(d))

编辑器提示 d 是字典类型。。。很奇怪。。。这是什么问题?
1679 次点击
所在节点    Python
12 条回复
geelaw
2021-05-05 21:45:34 +08:00
不确定你的 dumps 是什么,但我猜是 json.dumps 。原因是你没有正确 balance 序列化和解析的次数,read 方法得到的已经是字符串,接下来先 dumps 又 loads,两个操作抵消,自然只会得到一个字符串。

正确的做法是 read 的返回值直接 loads 。
ALLROBOT
2021-05-05 22:03:36 +08:00
@geelaw
dumps 的是 stream_header.txt 的文本,上面{xxx}的就是了
我也是挺无奈的,不这样改就报错
JSONDecodeError: Expecting property name enclosed in double quotes,错误最早的序列位置在 with open 这两个函数。。。
明明 str 的值没用单引号啥。。
chenqh
2021-05-05 22:17:14 +08:00
@ALLROBOT 你 print 下 header 看一下, print(repr(header_.read())
ferencz
2021-05-05 22:25:07 +08:00
from json import loads

with open('stream_header.txt', 'r', encoding='utf-8') as f:
json_text = loads(f.read())
print(json_text, '\n', type(json_text))

输出:
{'appId': 'amp-ios-10000', 'accessToken': 'xxxxxxxxxxxxxxx', 'User-Agent': 'Mozilla/5.0', 'Content-Type': 'application/json;charset=UTF-8', 'Host': 'messageapi.campusphere.net', 'Accept-Encoding': 'gzip'}
<class 'dict'>

没毛病啊~
kkbblzq
2021-05-05 22:28:13 +08:00
如果你这个 dumps 是 json.dumps,那你 dumps 又 loads 当然是文本,如果你 loads 报错 dumps 一遍又不能解决问题。。。这 dumps 纯属掩耳盗铃
renmu123
2021-05-05 22:30:03 +08:00
json.loads 会将 json 反序列化为 python 对象
d 是 json 中的 object 所以反序列化成了 dict,有那里奇怪的吗?
ALLROBOT
2021-05-05 22:44:14 +08:00
就回了''两个单引号
@chenqh
ALLROBOT
2021-05-05 22:45:18 +08:00
@ferencz 但我这儿的编辑器回复<class 'str'>,不知道啥原因,编辑器有 bug ?
ALLROBOT
2021-05-05 22:45:52 +08:00
pycharm 社区版的,python 依赖包正常装
chenqh
2021-05-05 22:59:54 +08:00
@ALLROBOT 我知道了,你要把控 header_.read() 保存到一个变量里面

```
with open("stream_header.txt","r")as header_:
r = header_.read()
print(repr(r))
header = json.loads(r)
print(type(header))
```
header=json.loads(dumps(header_.read()))
print(type(header))
imycc
2021-05-05 23:03:15 +08:00
嘛,找个终端试试就知道了。dumps 和 loads,一个负责序列化一个负责反序列化,写入文件前序列化一次,从文件读回来的时候就要反序列化一次。多或者少都会出问题。

In [1]: import json

In [2]: json.loads('{"foo": "bar"}')
Out[2]: {'foo': 'bar'}

In [3]: json.dumps('{"foo": "bar"}')
Out[3]: '"{\\"foo\\": \\"bar\\"}"'

In [4]: json.loads(json.dumps('{"foo": "bar"}'))
Out[4]: '{"foo": "bar"}'


直接回归到原本的问题,为什么从文件里面加载不出数据就好。看报错只是说有属性没用双括号括起来。

你存进去文件里面的时候,也要用 json.dump 存进去,才是合法的 json 字符串。直接 print 一个字典就粘贴进去文件是不对的,非常常见的新手错误。

&& 如果涉及到的都是文件的操作,只需要将打开的文件对象给 json.load 和 json.dump 操作就好,不需要读成字符串再调用 json.loads

with open('xxx.txt') as fp:
data = json.load(fp)
ALLROBOT
2021-05-06 14:26:51 +08:00
@ALLROBOT
搞懂 AttributeError: 'str' object has no attribute 'items'发生原因了。。。header 得改 dict 类型,body 改 str 类型
# 读取协议头
with open("stream_header.txt")as header_:
header=loads(header_.read())
# 读取学生身份 id 以及时间戳
with open("old_identity_information.txt")as old_:
date=(old_.read())
这样编辑器就不会报错了,读写文件其实没啥毛病的哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/775032

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX