• 52389

    文章

  • 521

    评论

  • 43

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

python之 字典顺序 与 md5 与 json转字符串跨语言对接

695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网站提供最新的站长新闻,各种互联网资讯。 还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿大家一起进步!

前言:

在这里先说明标题python为什么没有指明版本。因为我这次讲述的一个把py2代码改为py3代码的真实实例。

背景:

笔者有个项目,笔者的python项目需要与后端.Net用md5加密对接api。结果调试了非常久后终于好了。现在笔者的代码基本改用py3,于是尝试升级下。结果.....嗯~于是写下本文,分享下关于python版本间 字典序列 json转字符串 md5加密 跨语言对接 遇到的各种各样的坑!!!

本来想分文章讲述的。但是毕竟是一个项目实例。就放在一起说了。至于.Net调试时打印的文本是怎么样的,我就只是描述下好了。.Net笔者不会,而且项目已久,也没时间找别人对接调试了。

正文:

假设我们的数据是

(ps: 有人说我e打错为el了。其实我是故意的!!!如果是e,py2下字典序列就会看上去有一点规律可寻。为了避免有人钻空子,只能这样了)

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

现在要做的是

python客户端 .Net服务器
1、把 字典 转成 字符串  
2、把 字符串 用 md5加密  
3、把 加密结果 和 字符串 发给服务器(.net) 3*、服务器 把字符串转字典后,重复1、2
  4*、服务器 匹配 原加密结果 与 自己计算的加密结果。相同则返回正确

 

1、  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-1、py2的字典序列问题

py2的字典是无序的,但是key不变位置不变时,就算值改变,转字符串的key顺序是相对固定的。也就是说,还好只需要调试成功一次就行了(如果不加/改/删key的话)。

解决方法有3种

方法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-2、json.dumps空格问题

在python中,字典转字符串无论在那个版本里, 和:后面都会有空格。因此,当python对接其他语言时,如果对字典md5加密,则需要处理掉空格问题。

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

简单处理下就好。不要直接replace掉空格,因为内容字符串可能原本就有空格,例如英文名、地址之类的。

 

2、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
"""

3、汇总

以上面的例子为例。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

 

 

 


 转载至链接:https://my.oschina.net/jacky326/blog/3039177。


转载原创文章请注明出处,转载至: 梁钟霖个人博客www.liangzl.com

您觉喜欢本网站,或者觉得本文章对您有帮助,那么可以选择打赏。
打赏多少,您高兴就行,谢谢您对梁钟霖这小子的支持! ~(@^_^@)~

  • 微信扫一扫

  • 支付宝扫一扫

    支付宝打赏

1条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤
注册梁钟霖个人博客