前幾天用Python的Bottle框架寫個小web程式,在進行Ajax交互之時,前端則先用 JSON.stringify 來將類序列化,然後用escape() 函數將其編碼,確保傳輸正確。 再基本上配合上Jquery的$.ajax應該就可以了,可能是經驗不足,即使編碼之後的數據依然在 Python ...
前幾天用Python的Bottle框架寫個小web程式,在進行Ajax交互之時,前端則先用 JSON.stringify 來將類序列化,然後用escape() 函數將其編碼,確保傳輸正確。
再基本上配合上Jquery的$.ajax應該就可以了,可能是經驗不足,即使編碼之後的數據依然在 Python 中難以處理。
後來慢慢思考出一種方式,在網上也發現了類似的方式,於是將其實現。
基本思路如下:
escape('你好世界ABC');
//返回 "%u4F60%u597D%u4E16%u754CABC"
這串字元串提交到Bottle後,我利用Python 的 urllib 進行解碼,結果發現一個問題。。
>>> urllib.parse.unquote('%u4F60%u597D%u4E16%u754CABC')
'%u4F60%u597D%u4E16%u754CABC'
>>>
這個字元串該是什麼樣子還是什麼樣子,於是研究了片刻,然後傻逼的發現,這個壓根就已經不是URL編碼的字元了,不能用 unquote解了。。
我們應該用 decode('UTF-8')!
%uXXXX 是Javascript轉成 Unicode 的樣子。所以我們必須要使它變成 \uXXXX 的Unicode的標準形式
而且Python中 unquote 只能對str進行URL解碼,所以這個是對Unicode編碼的中文字元是無法解開的,那麼我就必須使用 decode('UTF-8');
但是收到的字元又是str,不存在什麼decode,只有encode。後來查了下手冊找到了個 urllib.parse.unquote_to_bytes 函數,可對Str進行URL解碼,並且返回 byte。
對的,要的就是這個,然後依據返回的byte,就可以對其使用 decode 。
於是我就寫了一個:
def load_json(value):
value = value.replace('%u','\\u') #將%uxxxx 替換換 \uxxxx 這才可以進行utf-8解碼
byts = urllib.parse.unquote_to_bytes(value) #返回的 byte
byts = byts.decode('UTF-8') # decode UTF-8 解碼只能解開 \uXXXX 的Unicode 標準形式
return json.loads(byts)
並且做以下測試:
escape('{"value":[123,"你好世界ABC"]}')
//"%7B%22value%22%3A%5B123%2C%22%u4F60%u597D%u4E16%u754CABC%22%5D%7D"
Python Shell:
>>> load_json('%7B%22value%22%3A%5B123%2C%22%u4F60%u597D%u4E16%u754CABC%22%5D%7D')
{'value': [123, '你好世界ABC']}
恭喜測試成功,看起來已經成功了。
總結:
這樣的話,縱使再如何的字元,都會被Unicode編碼。Javascript採用 escape(其他也行)來對字元進行UTF-8編碼,雖然得到的是%uXXXX,但是你可以傳化為 \uXXXX 的標準形式。
而且就算某些特別任性瀏覽器不會變成 %uXXXX,我們也只是 替換的%u,並不會影響實際的字元。
過程:
Javascript Object -> JSON.stringify(obj) -> escape(json_str) -> 瀏覽器的自動URL編碼(任性除外) -> Python urllib URL decode -> %uXXXX 替換 \uXXXX -> decode('UTF-8') -> json.load();
這隻是一點經驗之談,如果有任何錯誤或更好之處,歡迎指正,向其學習,定當謝過。