Python 将字符串转为字典

有如下字符串:

'{"name" : "apollo_miracle", "gender" : "male", "age": 18}'

想转化为字典格式:

{'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

方法一:通过 json 来转换

In [1]: import json

In [2]: user_info = '{"name" : "apollo_miracle", "gender" : "male", "age": 18}'

In [3]: user_dict = json.loads(user_info)

In [4]: user_dict
Out[4]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

但是使用 json 进行转换存在一个潜在的问题。

由于 json 语法规定 数组或对象之中的字符串必须使用双引号,不能使用单引号 ,因此下面的转换是错误的:

In [5]: user_info_02 = "{'name' : 'apollo_miracle', 'gender' : 'male', 'age': 18}"

In [6]: user_dict_02 = json.loads(user_info_02)
---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
<ipython-input-7-9d7814a11ca8> in <module>
----> 1 user_dict_02 = json.loads(user_info_02)

d:\python\python36\lib\json\__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pa
irs_hook, **kw)
    352             parse_int is None and parse_float is None and
    353             parse_constant is None and object_pairs_hook is None and not kw):
--> 354         return _default_decoder.decode(s)
    355     if cls is None:
    356         cls = JSONDecoder

d:\python\python36\lib\json\decoder.py in decode(self, s, _w)
    337
    338         """
--> 339         obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    340         end = _w(s, end).end()
    341         if end != len(s):

d:\python\python36\lib\json\decoder.py in raw_decode(self, s, idx)
    353         """
    354         try:
--> 355             obj, end = self.scan_once(s, idx)
    356         except StopIteration as err:
    357             raise JSONDecodeError("Expecting value", s, err.value) from None

JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

解决方案:将字符串中的单引号改为双引号。

定义如下函数:

import json
import re

def str_2_dict(my_str):
    try:
        my_dict = json.loads(my_str)
    except json.JSONDecodeError:
        my_str = re.sub(r"'", '"', my_str)
        my_dict = json.loads(my_str)

    return my_dict

再次进行转换,没有问题

In [7]: import json
   ...: import re
   ...: 
   ...: def str_2_dict(my_str):
   ...:     try:
   ...:         my_dict = json.loads(my_str)
   ...:     except json.JSONDecodeError:
   ...:         my_str = re.sub(r"'", '"', my_str)
   ...:         my_dict = json.loads(my_str)
   ...: 
   ...:     return my_dict
   ...: 

In [8]: user_dict = str_2_dict(user_info)

In [9]: user_dict_02 = str_2_dict(user_info_02)

In [10]: user_dict
Out[10]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

In [11]: user_dict_02
Out[11]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

方法二:通过 eval

In [12]: user_dict = eval(user_info)

In [13]: user_dict
Out[13]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

In [14]: user_dict_02 = eval(user_info_02)

In [15]: user_dict_02
Out[15]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

通过 eval 进行转换就不存在上面使用 json 进行转换的问题。但是,使用 eval 却存在安全性的问题

比如下面的例子:

In [16]: user_info = input("输入用户信息:")
输入用户信息:__import__('os').system('dir')

In [17]: user_dict = eval(user_info)
驱动器 G 中的卷是 工作
 卷的序列号是 C65E-5C90
... 此处省略一万字 ...

如果再输入一些删除命令,则可以把整个目录清空了!后果不敢想象。。。

方法三:通过 literal_eval

In [18]: import ast

In [19]: user_info = '{"name" : "apollo_miracle", "gender" : "male", "age": 18}'
    ...: user_info_02 = "{'name' : 'apollo_miracle', 'gender' : 'male', 'age': 18}"

In [20]: user_dict = ast.literal_eval(user_info)

In [21]: user_dict
Out[21]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

In [22]: user_dict_02 = ast.literal_eval(user_info_02)

In [23]: user_dict_02
Out[23]: {'name': 'apollo_miracle', 'gender': 'male', 'age': 18}

In [24]: user_info = input("输入用户信息:")
输入用户信息:__import__('os').system('dir')

In [25]: user_info = ast.literal_eval(user_info)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-25-c546997ab177> in <module>
----> 1 user_info = ast.literal_eval(user_info)

d:\python\python36\lib\ast.py in literal_eval(node_or_string)
     83                     return left - right
     84         raise ValueError('malformed node or string: ' + repr(node))
---> 85     return _convert(node_or_string)
     86
     87

d:\python\python36\lib\ast.py in _convert(node)
     82                 else:
     83                     return left - right
---> 84         raise ValueError('malformed node or string: ' + repr(node))
     85     return _convert(node_or_string)
     86

ValueError: malformed node or string: <_ast.Call object at 0x0000019F3B9BEE10>

使用 ast.literal_eval 进行转换既不存在使用 json 进行转换的问题,也不存在使用 eval 进行转换的 安全性问题,因此推荐使用 ast.literal_eval

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值