http://funhacks.net/2016/04/24/python_%E5%B0%86%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E4%B8%BA%E5%AD%97%E5%85%B8/
引言
在工作中遇到一個小問題,需要将一個
python
的字元串轉為字典,比如字元串:
1 | user_info = '{"name" : "john", "gender" : "male", "age": 28}' |
我們想把它轉為下面的字典:
1 | user_dict = {"name" : "john", "gender" : "male", "age": 28} |
有以下幾種方法:
通過 json 來轉換
1 2 3 4 5 6 | >>> import json >>> user_info= '{"name" : "john", "gender" : "male", "age": 28}' >>> user_dict = json.loads(user_info) >>> user_dict {u'gender': u'male', u'age': 28, u'name': u'john'} |
但是使用
json
進行轉換存在一個潛在的問題。
由于
json
文法規定 數組或對象之中的字元串必須使用雙引号,不能使用單引号 (官網上有一段描述是 “A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes” ),是以下面的轉換是錯誤的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> import json >>> user_info = "{'name' : 'john', 'gender' : 'male', 'age': 28}" # 由于字元串使用單引号,會導緻運作出錯 >>> user_dict = json.loads(user_info) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 380, in raw_decode obj, end = self.scan_once(s, idx) ValueError: Expecting property name: line 1 column 2 (char 1) |
通過 eval
1 2 3 4 5 6 7 8 9 | >>> user_info = '{"name" : "john", "gender" : "male", "age": 28}' >>> user_dict = eval(user_info) >>> user_dict {'gender': 'male', 'age': 28, 'name': 'john'} >>> user_info = "{'name' : 'john', 'gender' : 'male', 'age': 28}" >>> user_dict = eval(user_info) >>> user_dict {'gender': 'male', 'age': 28, 'name': 'john'} |
通過
eval
進行轉換就不存在上面使用
json
進行轉換的問題。但是,使用
eval
卻存在
安全性的問題
,比如下面的例子:
1 2 3 4 5 6 7 8 | # 讓使用者輸入 `user_info` >>> user_info = raw_input('input user info: ') # 輸入 {"name" : "john", "gender" : "male", "age": 28},沒問題 >>> user_dict = eval(user_info) # 輸入 __import__('os').system('dir'),user_dict 會列出目前的目錄檔案! # 再輸入一些删除指令,則可以把整個目錄清空了! >>> user_dict = eval(user_info) |
通過 literal_eval
1 2 3 4 5 6 7 8 9 10 | >>> import ast >>> user = '{"name" : "john", "gender" : "male", "age": 28}' >>> user_dict = ast.literal_eval(user) >>> user_dict {'gender': 'male', 'age': 28, 'name': 'john'} user_info = "{'name' : 'john', 'gender' : 'male', 'age': 28}" >>> user_dict = ast.literal_eval(user) >>> user_dict {'gender': 'male', 'age': 28, 'name': 'john'} |
使用
ast.literal_eval
進行轉換既不存在使用
json
進行轉換的問題,也不存在使用
eval
進行轉換的
安全性問題
,是以推薦使用
ast.literal_eval
。
參考資料
- JSON
- python: single vs double quotes in JSON - Stack Overflow
- Using python’s eval() vs. ast.literal_eval()? - Stack Overflow
- JSON對象 – JavaScript 标準參考教程(alpha)