Python对象转换REST、Json(下) December 22, 2006
★ REST格式
REST格式采用XML标准,这里我们采用xml.dom.minidom来构建REST数据。这里采用递归函数在父节点下转换当前数据:
def simple2rest(self, instance, pnode, force_child=False):
if isinstance(instance[1], (DictType)):
…
elif isinstance(instance[1], ListType):
…
elif instance[0][:-1].lower() == ’s’:
…
else:
…
instance是当前数据对象二元组(名称,值),其中pnode是上级数据结构对应的DomNode,force_child是标识强制在父节点下建立,这主要是满足list类型的需要,下面会逐个介绍。
A)字典类型:
建立字典节点,并遍历字典所有数据:
node = pnode.appendChild(pnode.ownerDocument.createElement(instance[0]))
for name in list(instance[1]):
self.simple2rest((name, instance[1][name]), node)
B)列表类型:
过程和字典类型处理方式类似,但如果一个类中有下列情况:
class mybook:
chapters[] = …
他对应的REST应该是:
<mybook>
<chapters>
<chapter … >…</chapter>
<chapter … >…</chapter>
…
</chapters>
</mybook>
这样就需要根据字段名称生成REST中的集合名和集合项目名:
itemname, itemsname = instance[0], instance[0] + ’s’
if instance[0][-2:].lower() == ‘es’:
itemname, itemsname = instance[0][:-2], instance[0]
elif instance[0][:-1].lower() == ’s’:
itemname, itemsname = instance[0][:-1], instance[0]
其他基本和字典一样
C)值类型:
首先对于列表元素数据,将列表内容作为列表集合标签的属性处理,由于tag属性不能重名,因此必须先建立单独的节点:
if force_child:
pnode = pnode.appendChild(pnode.ownerDocument.createElement(instance[0]))
同一个值可以有两种形式存在,如:
<tag some=”…” value=”…”>或
<tag some=”…”>…</tag>
一个Tag最多只可能有一个作为TextNode内容,因此这里的处理方式是将字段名为“value”的数据处理为textnode。
if force_child or instance[0].lower() == ‘value’:
pnode.appendChild(pnode.ownerDocument.createTextNode(str(instance[1])))
else:
pnode.setAttribute(instance[0], str(instance[1])
★ 值类型过滤
在Json中,布尔表示为“true”和“false”,而在REST中通常会表示“1”和“0”,另外枚举的处理也需要转换为字串,比如“read”比“1”要好的多。上面都是默认用Python的str函数转换值类型,为了满足上述要求,必须做针对类型的过滤器:
ins_value = self.fmtfilters.type2str(instance[1])
class ValueFilters:
trans_filters = Nonedef type2str(self, instance):
if self.trans_filters and self.trans_filters.has_key(type(instance)):
return self.trans_filters[type(instance)](instance)
return str(instance)
在简单类型转换过程中,会先查找某个类成员是否有对应的转换函数,如果有则不调用默认的obj2simple:
fmtname = ‘format_’ + name + ‘_field’
if hasattr(instance, fmtname):
clsdict[name] = getattr(instance, fmtname)()
else:
clsdict[name] = obj2simple(field)