python之 字典順序 與 md5 與 json轉字符串跨語言對接

前言:

在這裏先說明標題python爲何沒有指明版本。由於我此次講述的一個把py2代碼改成py3代碼的真實實例。python

背景:

筆者有個項目,筆者的python項目須要與後端.Net用md5加密對接api。結果調試了很是久後終於好了。如今筆者的代碼基本改用py3,因而嘗試升級下。結果.....嗯~因而寫下本文,分享下關於python版本間 字典序列 json轉字符串 md5加密 跨語言對接 遇到的各類各樣的坑!!!c++

原本想分文章講述的。可是畢竟是一個項目實例。就放在一塊兒說了。至於.Net調試時打印的文本是怎麼樣的,我就只是描述下好了。.Net筆者不會,並且項目已久,也沒時間找別人對接調試了。json

正文:

假設咱們的數據是後端

(ps: 有人說我e打錯爲el了。其實我是故意的!!!若是是e,py2下字典序列就會看上去有一點規律可尋。爲了不有人鑽空子,只能這樣了)api

d = {
    'a':1,
    'b':2,
    'c':3,
    'd':4,
    'el':5,
    'f':6,
    'g':7,
}

如今要作的是服務器

python客戶端 .Net服務器
一、把 字典 轉成 字符串  
二、把 字符串 用 md5加密  
三、把 加密結果 和 字符串 發給服務器(.net) 3*、服務器 把字符串轉字典後,重複一、2
  4*、服務器 匹配 原加密結果 與 本身計算的加密結果。相同則返回正確

 

一、  py2與py3的字典轉字符串,與其餘語言的區別

爲了顯示版本我加上打印sys.version來區分版本。代碼十分簡單。可是結果卻顯然有問題函數

import sys
import json
d = {
    'a':1,
    'b':2,
    'c':3,
    'd':4,
    'el':5,
    'f':6,
    'g':7,
}
print(sys.version)
print(json.dumps(d))
"""
----------py2-------------
#py2的字典是無序的
2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)]
{"a": 1, "el": 5, "c": 3, "b": 2, "d": 4, "g": 7, "f": 6}
----------py3-------------
#py3的字典是有序的
3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
{"a": 1, "b": 2, "c": 3, "d": 4, "el": 5, "f": 6, "g": 7}
----------.net----------------
.net的字符串在,和:後面是沒有空格的,並且是按順序的。下面的結果是基於之前對接的測試結果推測。
{"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7}
"""

這裏之前py2對接的時候排查了很久!拿了電腦去雙雙一步步調試才知道緣由。測試

 

1-一、py2的字典序列問題

py2的字典是無序的,可是key不變位置不變時,就算值改變,轉字符串的key順序是相對固定的。也就是說,還好只須要調試成功一次就好了(若是不加/改/刪key的話)。加密

解決方法有3種spa

方法1 「投桃報李」:

讓服務器(.net)把dist的順序改成跟咱們轉字符串後的順序同樣。

ps:咱們當初是這樣解決啦。由於沒辦法且這樣最快解決問題。若是api是外部的話就GG了。

方法2 「圍魏救趙」:

在python裏爲了應對這種狀況,在內置函數collections有OrderedDict(有序字典)建立有序字典。操做與使用和dist相似,十分方便。

ps:這是比較推薦的方法可是當字典下還有字典的話,也會有問題。若是子字典是dist,則子dist依然是無序的。若是子字典是OrderedDict會把OrderedDict的類名也帶上。

import sys
import collections
d = collections.OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
d['el'] = 5
d['f'] = 6
d['g'] = 7
print(sys.version)
print(json.dumps(d))
"""
2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)]
{"a": 1, "b": 2, "c": 3, "d": 4, "el": 5, "f": 6, "g": 7}
"""

方法3: 「無中生有」

代碼不說了,就是本身模擬json把字典按本身順序拼接成字符串。不建議使用,很容易致使沒法解析回json的。

 

1-二、json.dumps空格問題

在python中,字典轉字符串不管在那個版本里, 和:後面都會有空格。所以,當python對接其餘語言時,若是對字典md5加密,則須要處理掉空格問題。

strings = strings.replace(': ',':').replace(', ',',')

簡單處理下就好。不要直接replace掉空格,由於內容字符串可能本來就有空格,例如英文名、地址之類的。

 

二、python版本間md5加密的不一樣問題

py3中md5加密必須把字符串轉成byte類型才能加密。py2中不強制要求。基本寫法是

import hashlib

string = 'xxxx'
m = hashlib.md5()
m.update(string.encode(encoding='utf-8'))
m.hexdigest()

在沒有中文的狀況下,py2與py3的結果是必定相同的。有些文章說,有中文時結果會不同。可是我實際測試結果是同樣的。惟一區別只有encode的結果,md5結果同樣。不過你們仍是留意下。

import sys
import hashlib

print(sys.version)
s = 'kid'
s1 = s.encode(encoding='utf-8')
print(s1)
m = hashlib.md5()
m.update(s1)
print(m.hexdigest())
s = u'中文'
s1 = s.encode(encoding='utf-8')
print(s1)
m = hashlib.md5()
m.update(s1)
print(m.hexdigest())
"""
---------py2--------
2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)]
kid
7de007e43f108e4b54b079f66e4285d8
涓枃
a7bac2239fcdcb3a067903d8077c4a07
---------py3---------
3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
b'kid'
7de007e43f108e4b54b079f66e4285d8
b'\xe4\xb8\xad\xe6\x96\x87'
a7bac2239fcdcb3a067903d8077c4a07
"""

三、彙總

以上面的例子爲例。py2的正確加密方法是

import sys
import json
import collections
d = collections.OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
d['el'] = 5
d['f'] = 6
d['g'] = 7
print(sys.version)
string = json.dumps(d).replace(': ',':').replace(', ',',')
print(string)
m = hashlib.md5()
m.update(string.encode(encoding='utf-8'))
print(m.hexdigest())
"""
2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)]
{"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7}
d94f30c6cc9b1fc05ddcb04c920d5351
"""

py3的正確加密方法是

import hashlib
import sys
import json
d = {
    'a':1,
    'b':2,
    'c':3,
    'd':4,
    'el':5,
    'f':6,
    'g':7,
}
print(sys.version)
string = json.dumps(d).replace(': ',':').replace(', ',',')
print(string)
m = hashlib.md5()
m.update(string.encode(encoding='utf-8'))
print(m.hexdigest())
"""
3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
{"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7}
d94f30c6cc9b1fc05ddcb04c920d5351
"""

若是跨語言的加密匹配這樣是正確的。對於python對python之間,只要字典順序結構相同,同版本之間的md5校驗是同樣的。

據我所知c++ .Net的json字符串 , : 都是沒有空格的。具體要api實測時調試才清楚。

 

總結:

以上就是我項目中遇到的問題和處理方式。

1字典順序問題 (py2最好用OrderedDict代替dist)

2md5加密問題 (不管py2仍是py3都加上.encode(encoding='utf-8')保險)

3json轉字符串,跨語言對接問題問題 (對接要實際調試下,就python對接.Net而言,須要處理掉字符串: , 後面的空格,字符串才徹底一致,MD5加密就更不用說了)

 

轉載請註明出處:https://my.oschina.net/jacky326/blog/3039177

相關文章
相關標籤/搜索