0

我有一组我使用创建的 python 对象eulxml.xmlmap.XmlObject(我使用这种方法主要是因为我正在使用 eXistDB 服务器并且 eulxml 提供了一个非常简单的映射功能)。我能够成功查询我的 eXistDB 并将 xquery 结果集加载到我创建的一些 python 对象中。我的问题是,当我将这些对象传递给网络服务器时(使用 Angular 作为前端),我希望能够将这些对象作为 JSON 写出来。

我试过使用 jsonpickle 但似乎 eulxml 正在做某种延迟加载魔法。对 jsonpickle 将我的对象序列化为 json 的标准调用给了我这个结果:

蟒蛇代码:

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 代码更改为设置 unpickable=False,我得到的只是一组空的 json(这意味着结构存在于正确数量的花括号和方括号中,但实际上没有数据。json 输出是只是花括号和方括号)。

我想也许如果我尝试访问该字段中的一个值,然后输出可能有效的 json(至少对于我访问的字段)但没有运气。我得到与上述相同的结果(是的,我已经仔细检查过对象本身是否有数据)。

在这一点上,我有点不知所措。我可以迁移到 BeautifulSoup 之类的东西,但这意味着要编写更多代码(eulxml 让我只需将 xpath 指定为我想要填充属性的值和 bing,我就完成了)。jsonpickle 有什么我缺少的吗?还是我应该看看另一个 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')
4

2 回答 2

0

是的,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方法会直接返回字段的值

于 2019-10-22T12:56:19.127 回答
0

我能够弄清楚这个问题(有点)。所以我把它贴在这里,以防其他人有同样的问题。

问题似乎是属性没有添加到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。这也假设所有对象集合都继承自这个基类(在我的特定模型中,这是真的,所以这不是问题)。

于 2018-04-25T16:56:29.843 回答