今天在進行django開發的過程中遇到了一個非常棘手的問題, 因為需求原因, 需要將一份數據存為json格式到數據庫中, 如下面這種格式:
list_1 = [{"name":"lowman", "age":"18"},{"name":"lowman1", "age":None}]
開發環境是python2, 在后端接收到數據,打印數據是這樣的:
[{u"name":u"lowman", u"age":u"18"},{u"name":u"lowman1", u"age":None}]
里面的所有的字符串元素都是unicode類型的, 如果不使用json.dumps()進行轉換直接保存到數據庫中(TextField),然后再取出,是這樣格式的數據(編碼后保存還是unicode類型, 數據庫編碼格式是utf-8)
u'[{u"name":u"lowman", u"age":u"18"},{u"name":u"lowman1", u"age":None}]'
這時如果使用json.loads()進行轉換, 會拋出異常(使用json.loads(),元素不可以是unicode類型), 但是如果使用json.dumps()將數據進行一下轉換,再保存到數據庫中時,卻是這樣的數據形式
"[{u'name':u'lowman', u'age':u'18'},{u'name':u'lowman1', u'age':None}]"
這時使用json.loads()進行轉換后,再使用django rest framework 的 Response() 向前端進行返回, 前端接收的數據卻是這樣的, 且無法轉化為list數據
"[{u'name':u'lowman', u'age':u'18'},{u'name':u'lowman1', u'age':None}]"
各種求解無果,問題症結就在列表嵌套字典, 在我的環境里進行encode() 企圖將數據轉換為str格式的字符串時無法作用到里面的一層數據, 字典的元素仍然是unicode類型, 各種磨難尋找后, 終於發現了一個神器, 那就是eval() 函數, 它可以神奇的將最外層的數據的雙引號或者單引號去掉, 轉換為原始格式的數據, 並且可以將里面所有的unicode元素字符串轉換為str格式的字符串
list_str = u'[{u"name":u"lowman", u"age":"18"},{u"name":u"lowman1", u"age":None}]'
list_str = eval(list_str)
print(type(list_str))
print(list_str)
my_str = "123"
my_str = eval(my_str)
print(type(my_str))
print(my_str)
輸出結果
<class 'list'> [{'name': 'lowman', 'age': '18'}, {'name': 'lowman1', 'age': None}] <class 'int'> 123
回到原來的需求:
先使用eval() 處理后端接收到的數據, 再使用json.dumps()進行處理, 然后保存到數據庫, 數據形式是這樣的(話說這樣格式的數據其實才是滿足我們本次需求的)
[{'name': 'lowman', 'age': '18'}, {'name': 'lowman1', 'age': None}]
這時, 保存到數據庫中的數據才是一個json格式的數據, 當想要向前端返回數據時, 使用json.loads() 或者仍然使用eval()函數進行處理一下從數據庫中取出的數據, 再使用Django rest framework 的 Respose() 向前端進行返回.前端發送ajax請求成功后接收到數據格式是這樣的(注意這時對應到Python字典數據的鍵是沒有引號的):
[{name: 'lowman', age: '18'}, {name: 'lowman1', age: None}]
至此,問題解決, eval 果然神奇......................................................................
經過一位大佬的提醒,這樣子使用 eval 函數,是存在安全性問題的(比如數據中存在腳本代碼,或者 sql 語句),事實上 eval 是一個非常強大的函數,它具備了很多實用的功能,但是如果對於數據源不具備可信任性,可以使用 ast.literal_eval 進行替代,特別是在進行 web server 開發時,需要接收處理前端傳遞的參數。。。
