JSON 从 python 中的 eulxml 序列化时序列化为空
JSON Serialization is empty when serialising from eulxml in python
我在 python 中使用 eXistDB 并利用 eulxml
库来处理从数据库中的 xml 到自定义对象的映射。然后我想将这些对象序列化为 json(供另一个应用程序使用),但我 运行 遇到了问题。 jsonpickle
不起作用(它最终返回各种多余的垃圾,值是字段实际上没有编码,而是它们的 eulxml 类型)和标准 json.dumps()
是只是给我空 json(这是在尝试实施详细的解决方案 here 之后)。问题似乎源于 __dict__
值未初始化 __oninit__
(因为它们被映射为 class 属性),因此 __dict__
在序列化时显示为空。这是一些示例代码:
可序列化Class对象
class Serializable(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# hack to fix _json.so make_encoder serialize properly
self.__setitem__('dummy', 1)
def _myattrs(self):
return [
(x, self._repr(getattr(self, x)))
for x in self.__dir__()
if x not in Serializable().__dir__()
]
def _repr(self, value):
if isinstance(value, (str, int, float, list, tuple, dict)):
return value
else:
return repr(value)
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
def keys(self):
return iter([x[0] for x in self._myattrs()])
def values(self):
return iter([x[1] for x in self._myattrs()])
def items(self):
return iter(self._myattrs())
基础Class
from eulxml import xmlmap
import inspect
import lxml
import json as JSON
from models.serializable import Serializable
class AlcalaBase(xmlmap.XmlObject,Serializable):
def toJSON(self):
return JSON.dumps(self, indent=4)
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)
实现 Base
的示例 Class
from eulxml import xmlmap
from models.alcalaMonth import AlcalaMonth
from models.alcalaBase import AlcalaBase
class AlcalaPage(AlcalaBase):
ROOT_NAME = "page"
id = xmlmap.StringField('pageID')
year = xmlmap.IntegerField('content/@yearID')
months = xmlmap.NodeListField('content/month', AlcalaMonth)
基础上的 toJSON()
方法是使用 Serializable
class 并返回空 json 的方法,例如“{}”。 to_json()
是我尝试实现类似 json 的实现,但它有自己的问题(出于某种原因,它无缘无故地跳过某些属性/子对象,但那是另一天的话题).
如果我尝试访问 myobj.keys
或 myobj.values
(两者都通过 Serializable
公开),我可以看到 属性 名称和值,正如我所期望的,但是我不知道为什么 json.dumps() 会产生一个空的 json 字符串。
有谁知道为什么我无法将这些对象序列化为 json?!几个星期以来,我一直在为此烦恼。任何帮助将不胜感激。
经过大量尝试,我终于能够用 jsonpickle 解决这个问题,只用了 3 行代码:
def toJson(self):
jsonpickle.set_preferred_backend('simplejson')
return jsonpickle.encode(self, unpicklable=False)
我使用 simplejson
消除了一些正在添加的附加对象符号,而 unpicklable
属性 删除了其余部分(我不确定这是否适用于默认 json
后端,因为我没有测试它)。
现在,当我在任何继承自该基础 class 的对象上调用 toJson() 时,我会变得非常好 json 并且工作出色。
我在 python 中使用 eXistDB 并利用 eulxml
库来处理从数据库中的 xml 到自定义对象的映射。然后我想将这些对象序列化为 json(供另一个应用程序使用),但我 运行 遇到了问题。 jsonpickle
不起作用(它最终返回各种多余的垃圾,值是字段实际上没有编码,而是它们的 eulxml 类型)和标准 json.dumps()
是只是给我空 json(这是在尝试实施详细的解决方案 here 之后)。问题似乎源于 __dict__
值未初始化 __oninit__
(因为它们被映射为 class 属性),因此 __dict__
在序列化时显示为空。这是一些示例代码:
可序列化Class对象
class Serializable(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# hack to fix _json.so make_encoder serialize properly
self.__setitem__('dummy', 1)
def _myattrs(self):
return [
(x, self._repr(getattr(self, x)))
for x in self.__dir__()
if x not in Serializable().__dir__()
]
def _repr(self, value):
if isinstance(value, (str, int, float, list, tuple, dict)):
return value
else:
return repr(value)
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
def keys(self):
return iter([x[0] for x in self._myattrs()])
def values(self):
return iter([x[1] for x in self._myattrs()])
def items(self):
return iter(self._myattrs())
基础Class
from eulxml import xmlmap
import inspect
import lxml
import json as JSON
from models.serializable import Serializable
class AlcalaBase(xmlmap.XmlObject,Serializable):
def toJSON(self):
return JSON.dumps(self, indent=4)
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)
实现 Base
的示例 Classfrom eulxml import xmlmap
from models.alcalaMonth import AlcalaMonth
from models.alcalaBase import AlcalaBase
class AlcalaPage(AlcalaBase):
ROOT_NAME = "page"
id = xmlmap.StringField('pageID')
year = xmlmap.IntegerField('content/@yearID')
months = xmlmap.NodeListField('content/month', AlcalaMonth)
基础上的 toJSON()
方法是使用 Serializable
class 并返回空 json 的方法,例如“{}”。 to_json()
是我尝试实现类似 json 的实现,但它有自己的问题(出于某种原因,它无缘无故地跳过某些属性/子对象,但那是另一天的话题).
如果我尝试访问 myobj.keys
或 myobj.values
(两者都通过 Serializable
公开),我可以看到 属性 名称和值,正如我所期望的,但是我不知道为什么 json.dumps() 会产生一个空的 json 字符串。
有谁知道为什么我无法将这些对象序列化为 json?!几个星期以来,我一直在为此烦恼。任何帮助将不胜感激。
经过大量尝试,我终于能够用 jsonpickle 解决这个问题,只用了 3 行代码:
def toJson(self):
jsonpickle.set_preferred_backend('simplejson')
return jsonpickle.encode(self, unpicklable=False)
我使用 simplejson
消除了一些正在添加的附加对象符号,而 unpicklable
属性 删除了其余部分(我不确定这是否适用于默认 json
后端,因为我没有测试它)。
现在,当我在任何继承自该基础 class 的对象上调用 toJson() 时,我会变得非常好 json 并且工作出色。