将Python对象序列化为JSON使用eulxml.xmlmap.XmlObject

时间:2018-04-22 22:37:16

标签: python json exist-db jsonpickle

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

我尝试过使用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代码来设置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')

2 个答案:

答案 0 :(得分: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。这也假设所有对象集合都继承自这个基类(在我的特定模型中,这是真的,因此它不是问题)。

答案 1 :(得分:0)

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

No package found with specified pattern: D:\a\r1\a\**\*.zip

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