Python对象转换REST、Json(上) December 22, 2006
参考资料:
★ 背景
Representational State Transfer(REST)和JavaScript Object Notation(Json)是现在互联网应用的常见数据表示规格。因此在服务器端开发网络应用时,服务端语言与REST和Json之间的互换非常重要,既内核对象存盘为REST/Json格式,以及REST/Json格式读盘重建内核对象。下面先介绍前者。
★ 简化对象数据模型
REST/Json共同的优点就是数据模型简单,其基本数据模型由三种组成:
A)字典:包括类在内,都采用{数据名:数据值},是唯一的数据命名方式
B)数组:作为一个字典的数据值保存同类数据集合
C)简单值:包括布尔,数值,字串等,实际的数据载体
因此将Python的数据类型简化为上述三种方式是存盘的第一步,首先将Python类型分类:
LIST_TYPES = (ListType, TupleType)
COMPLEX_TYPES = (InstanceType)
DICT_TYPES = (DictType)
VALUE_TYPES = (BooleanType, StringType, LongType, IntType, FloatType)
通过递归函数扫描对象数据成员:
def obj2simple(instance):
if isinstance(instance, LIST_TYPES):
return [obj2simple(o) for o in list(instance)]
elif isinstance(instance, COMPLEX_TYPES):
return cls2simple(instance)
elif isinstance(instance, DICT_TYPES):
return dict2simple(instance)
elif isinstance(instance, VALUE_TYPES):
return instance
dict2simple函数和list2sample一致,只是简单的转换字典数据并重建新字典。稍微麻烦点的就是复杂类类型转换,首先先建立有效类成员列表:
members = [(member, getattr(instance, member)) for member in dir(instance) if not callable(getattr(instance, member)) and not member.startswith(’_')]
这个成员列表将类函数以及以’_'开头的成员(私有)排除,剩下的做法其实就是一个dict2sample过程。
ok,建立一个复杂些的测试案例:
class scls:
def asdf(self):
pass
arr = [3, 5, 5]
n = 9
b = True
s = ’sfafds’
value = ‘xxxx’dic = {’a':3, ‘aa’:scls()}
class cls:
def asfl(self):
pass
i = 2
s = ‘asf’
clsarr = [2, ‘af’, scls(), scls()]
clsdic = {’a':34, ‘aa’:scls(), ‘d’:dic}
t = (4, ’ss’, dic)
转换结果:
{’i': ‘iii2′, ’s’: ‘asf’, ‘clsarr’: [2, ‘af’, {’arr’: [3, 5, 5], ‘b’: True, ’s’: ’sfafds’, ‘value’: ‘xxxx’, ‘n’: 9}, {’arr’: [3, 5, 5], ‘b’: True, ’s’: ’sfafds’, ‘value’: ‘xxxx’, ‘n’: 9}], ‘t’: [4, ’ss’, {’a': 3, ‘aa’: {’arr’: [3, 5, 5], ‘b’: True, ’s’: ’sfafds’, ‘value’: ‘xxxx’, ‘n’: 9}}], ‘clsdic’: {’a': 34, ‘aa’: {’arr’: [3, 5, 5], ‘b’: True, ’s’: ’sfafds’, ‘value’: ‘xxxx’, ‘n’: 9}, ‘d’: {’a': 3, ‘aa’: {’arr’: [3, 5, 5], ‘b’: True, ’s’: ’sfafds’, ‘value’: ‘xxxx’, ‘n’: 9}}}}
★ Json格式
通过Sample数据模型转换Json格式就简单多了,其实从前面的测试结果(str(sampleobj))看到的结果就是一个Json字串了,但是我们必须重写,因为Json对Boolean的标识和Python情况不同,另外,也不能满足对某些特殊返回形式的需要。
def simple2json(self, instance):
if isinstance(instance, (DictType)):
return ‘{’ + ‘,’.join([’”%s”=%s’ % (o, self.simple2json(instance[o])) for o in list(instance)]) + ‘}’
elif isinstance(instance, ListType):
return ‘[’ + ‘,’.join([self.simple2json(o) for o in instance]) + ‘]’
else:
return str(instance)
Leave a Reply