如何将eulxml.xmlmap.XmlObject创建的Python对象序列化为JSON
我之前也碰到过和你一模一样的场景——用eulxml的XmlObject对接eXistDB,成功拉取XQuery结果后,要转JSON给Angular前端,用jsonpickle确实容易踩坑,给你几个实用的解决方案:
因为XmlObject本质是映射XML结构的对象,自带很多XML相关的内部属性,jsonpickle会把这些冗余信息也序列化进去,反而给前端添乱。不如直接提取你需要的字段,转成Python原生的字典/列表,再用标准库的json模块序列化,完全适配前端需求。
举个例子,假设你的XmlObject类是MyRecord,包含title、author、publish_date字段,还有子元素列表related_items:
import json def xmlobj_to_dict(xml_obj): # 提取核心字段,日期类型可以转成字符串方便前端解析 data = { "title": xml_obj.title, "author": xml_obj.author, "publish_date": xml_obj.publish_date.isoformat() if xml_obj.publish_date else None } # 处理嵌套的子XmlObject列表,递归转成字典 if hasattr(xml_obj, 'related_items'): data["related_items"] = [xmlobj_to_dict(item) for item in xml_obj.related_items] return data # 假设你从eXistDB拿到了对象列表 records = MyRecord.from_query_result(query_result) # 批量转成JSON json_data = json.dumps([xmlobj_to_dict(record) for record in records])
这个方法的好处是你能精准控制前端拿到的字段,避免冗余,而且完全依赖Python标准库,不需要额外装包。
如果你的XmlObject结构特别复杂,手动提取字段太麻烦,可以利用eulxml的内置序列化功能先转成XML,再用xmltodict库把XML转成字典,最后转JSON:
import json import xmltodict def xmlobj_to_json(xml_obj): # 把XmlObject序列化为XML字符串 xml_str = xml_obj.serialize(pretty_print=True) # 解析XML为字典,attr_prefix=''可以去掉XML属性的前缀,让结构更干净 data_dict = xmltodict.parse(xml_str, attr_prefix='', dict_constructor=dict) # 转成JSON字符串 return json.dumps(data_dict) # 使用示例 single_record_json = xmlobj_to_json(your_single_xml_object)
注意如果XML有重复节点,xmltodict会自动转成列表,刚好符合JSON的数组格式,不过你可能需要根据前端需求调整xmltodict的参数,比如force_list来强制把某些节点转成列表。
如果你一定要用jsonpickle,那得自定义处理器,过滤掉XmlObject的内部属性,只序列化你需要的字段:
import jsonpickle class XmlObjectJsonHandler(jsonpickle.handlers.BaseHandler): def flatten(self, obj, data): # 只添加你需要的字段到序列化数据中 for field_name in ['title', 'author', 'publish_date']: if hasattr(obj, field_name): data[field_name] = getattr(obj, field_name) # 处理子元素列表 if hasattr(obj, 'related_items'): data['related_items'] = [jsonpickle.encode(item, unpicklable=False) for item in obj.related_items] return data # 给你的XmlObject类注册处理器 jsonpickle.handlers.register(MyRecord, XmlObjectJsonHandler) # 序列化时记得关掉unpicklable,避免生成jsonpickle特有的冗余字段 json_data = jsonpickle.encode(your_xml_object, unpicklable=False)
这个方法需要你手动维护要序列化的字段,灵活性不如前两个,而且jsonpickle生成的JSON可能还是有多余内容,所以优先推荐前两个方案。
内容的提问来源于stack exchange,提问作者Shane McGarry

