V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ALLROBOT
V2EX  ›  Python

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

  •  
  •   ALLROBOT · 2021-05-05 21:38:57 +08:00 · 1635 次点击
    这是一个创建于 1280 天前的主题,其中的信息可能已经有所发展或是发生改变。
    很奇怪的问题,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 是字典类型。。。很奇怪。。。这是什么问题?
    第 1 条附言  ·  2021-05-05 22:48:55 +08:00
    哦对了,dumps 是 json.dumps 的
    第 2 条附言  ·  2021-05-06 14:27:33 +08:00
    搞懂 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())
    这样编辑器就不会报错了,读写文件其实没啥毛病的哈哈
    12 条回复    2021-05-06 14:26:51 +08:00
    geelaw
        1
    geelaw  
       2021-05-05 21:45:34 +08:00 via iPhone
    不确定你的 dumps 是什么,但我猜是 json.dumps 。原因是你没有正确 balance 序列化和解析的次数,read 方法得到的已经是字符串,接下来先 dumps 又 loads,两个操作抵消,自然只会得到一个字符串。

    正确的做法是 read 的返回值直接 loads 。
    ALLROBOT
        2
    ALLROBOT  
    OP
       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
        3
    chenqh  
       2021-05-05 22:17:14 +08:00
    @ALLROBOT 你 print 下 header 看一下, print(repr(header_.read())
    ferencz
        4
    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
        5
    kkbblzq  
       2021-05-05 22:28:13 +08:00
    如果你这个 dumps 是 json.dumps,那你 dumps 又 loads 当然是文本,如果你 loads 报错 dumps 一遍又不能解决问题。。。这 dumps 纯属掩耳盗铃
    renmu123
        6
    renmu123  
       2021-05-05 22:30:03 +08:00 via Android
    json.loads 会将 json 反序列化为 python 对象
    d 是 json 中的 object 所以反序列化成了 dict,有那里奇怪的吗?
    ALLROBOT
        7
    ALLROBOT  
    OP
       2021-05-05 22:44:14 +08:00
    就回了''两个单引号
    @chenqh
    ALLROBOT
        8
    ALLROBOT  
    OP
       2021-05-05 22:45:18 +08:00
    @ferencz 但我这儿的编辑器回复<class 'str'>,不知道啥原因,编辑器有 bug ?
    ALLROBOT
        9
    ALLROBOT  
    OP
       2021-05-05 22:45:52 +08:00
    pycharm 社区版的,python 依赖包正常装
    chenqh
        10
    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
        11
    imycc  
       2021-05-05 23:03:15 +08:00   ❤️ 1
    嘛,找个终端试试就知道了。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
        12
    ALLROBOT  
    OP
       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())
    这样编辑器就不会报错了,读写文件其实没啥毛病的哈哈
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2930 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:56 · PVG 22:56 · LAX 06:56 · JFK 09:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.