将Python对象序列化为用eulxml.xmlmap.XmlObj

2024-04-29 03:14:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用eulxml.xmlmap.XmlObject创建了一组python对象(我使用这个方法主要是因为我使用的是eXistDB服务器,而eulxml提供了一个非常简单的映射函数)。我能够成功地查询eXistDB并将xquery结果集加载到我创建的一些python对象中。我的问题是,当我将这些对象传递给web服务器时,我希望能够将它们写成JSON(使用Angular作为前端)。你知道吗

我尝试过使用jsonpickle,但似乎eulxml正在发挥某种延迟加载的魔力。对jsonpickle的标准调用将我的对象序列化为json,结果如下:

python代码:

jsonpickle.encode(myObject)

结果:

"py/object": "models.alcalaPage.AlcalaPage", "context": 
{"namespaces": 
   {"exist": "http://exist.sourceforge.net/NS/exist"}
}, 
"node":  {
   "py/object": "lxml.etree._Element", 
   "py/seq": [
       {"py/object": "lxml.etree._Comment", "py/seq": []},
       {"py/object": "lxml.etree._Element", "py/seq": []},
       ...
    ]
   }... 

它似乎只输出属性的类型,而不输出属性本身的值。如果我将jsonpickle代码更改为set unpickable=False,我得到的只是一个空的json集(这意味着结构中有正确数量的花括号和方括号,但实际上没有数据)。json输出只是大括号和方括号)。你知道吗

我想,如果我尝试访问字段中的值,然后输出json,可能会正常工作(至少对于我访问的字段是这样),但运气不好。我得到了与上面所述相同的结果(是的,我已经仔细检查了对象本身是否有数据)。你知道吗

我现在有点不知所措。我可以迁移到类似BeautifulSoup的东西,但这意味着要编写更多的代码(eulxml允许我简单地将xpath指定为要填充属性的值,然后bing,我就完成了)。我是不是少了点什么?或者我应该看看另一个json包?或者可能我使这种方法变得比我需要的更困难,还有其他一些方法可以使用python查询eXistDB,然后将信息发送到使用Angular构建的前端应用程序。我愿意接受建议。你知道吗

我将在下面列出我的代码示例(我不会全部列出,因为我正在处理的对象可能超过10个):

包含eulxml的对象代码示例:

import jsonpickle
from eulxml.xmlmap import XmlObject


class AlcalaBase(XmlObject):

    def to_xml(self):
        return self.serializeDocument(pretty=True)

    def to_json(self):
        return jsonpickle.encode(self)

from eulxml import xmlmap
from models.alcalaBase import AlcalaBase

class AlcalaPage(AlcalaBase):
    ROOT_NAME = 'page'
    id = xmlmap.StringField('pageID')
    archive_page_number = xmlmap.StringField('archivistsPageNumber')
    year = xmlmap.IntegerField('content/@yearID')

Tags: 对象方法代码pyimportselfjsonobject
2条回答

我(有点)搞清楚了这个问题。所以我把它贴在这里,以防其他人也有同样的问题。你知道吗

问题似乎是没有将属性添加到dict中,因此在json过程中没有输出实际值。为了输出适当的对象,我在基类中编写了to_json()方法。注意:虽然我尽量保持这种通用性,但它在某种程度上特定于我的数据结构(因为我知道在给定的场景中会发生什么,而且因为我处理的是静态数据,所以我不必“证明未来”解决方案。任何采用此代码的人都应该使其适应给定的场景。你知道吗

from eulxml import xmlmap
import inspect
import lxml
import json as JSON

class AlcalaBase(xmlmap.XmlObject):

    def to_json(self, skipBegin=False):
        json = list()
        if not skipBegin:
            json.append('{')
        json.append(str.format('"{0}": {{', self.ROOT_NAME))
        for attr, value in inspect.getmembers(self):
            if (attr.find("_") == -1
                and attr.find("serialize") == -1
                and attr.find("context") == -1
                and attr.find("node") == -1
                and attr.find("schema") == -1):
                if type(value) is xmlmap.fields.NodeList:
                    if len(value) > 0:
                        json.append(str.format('"{0}": [', attr))
                        for v in value:
                            json.append(v.to_json())
                            json.append(",")
                        json = json[:-1]
                        json.append("]")
                    else:
                        json.append(str.format('"{0}": null', attr))
                elif (type(value) is xmlmap.fields.StringField
                        or type(value) is str
                        or type(value) is lxml.etree._ElementUnicodeResult):
                        value = JSON.dumps(value)
                        json.append(str.format('"{0}": {1}', attr, value))
                elif (type(value) is xmlmap.fields.IntegerField
                    or type(value) is int
                    or type(value) is float):
                    json.append(str.format('"{0}": {1}', attr, value))
                elif value is None:
                    json.append(str.format('"{0}": null', attr))
                elif type(value) is list:
                    if len(value) > 0:
                        json.append(str.format('"{0}": [', attr))
                        for x in value:
                            json.append(x)
                            json.append(",")
                        json = json[:-1]
                        json.append("]")
                    else:
                        json.append(str.format('"{0}": null', attr))
                else:
                    json.append(value.to_json(skipBegin=True))
                json.append(",")
        json = json[:-1]
        if not skipBegin:
            json.append('}')
        json.append('}')
        return ''.join(json)

从这个类继承的任何东西都可以序列化为json。这还假设所有对象集合都继承自这个基类(在我的特定模型中,这是真的,所以这不是问题)。你知道吗

是的,jsonpickle调用dict方法以便它工作,您可以在元类中使用以下内容:

class MyXmlObject(XmlObject):
    @property
    def __dict__(self):
        d = { 'ROOT_NAME': self.ROOT_NAME }
        for key, value in self._fields.items():
            if isinstance(value, fields.Field):
                if isinstance(value, fields.NodeListField):
                    d[key] = [x.__dict__ for x in getattr(self, key)]
                elif isinstance(value, fields.NodeField):
                    d[key] = getattr(self, key).__dict__
                else:
                    d[key] = getattr(self, key)
        return d

因此dict方法将直接返回字段的值

相关问题 更多 >