python - 来自邻接表的嵌套 JSON

标签 python json flask sqlalchemy adjacency-list

我有一个 Flask RESTful API 应用程序,它具有以下 SQLAlchemy 类和一个代表邻接列表的自引用键:

class Medications(db.Model):
    __tablename__ = 'medications'
    id = Column(Integer, primary_key=True)
    type = Column(String(64))
    name = Column(String(64))
    parent_id = Column(Integer, ForeignKey('medications.id'))
    children = relationship("Medications")

我想要从 Medications 类返回的嵌套 JSON,按照

"objects": [
    {
      "children": [
        {
          "id": 4, 
          "name": "Child1", 
          "parent_id": 3, 
          "type": "Leaf"
        }, 
        {
          "id": 5, 
          "name": "Child2", 
          "parent_id": 3, 
          "type": "Leaf"
        }
      ], 
      "id": 3, 
      "name": "CardioTest", 
      "parent_id": null, 
      "type": "Parent"
    }
  ], 

根据 how-to-create-a-json-object-from-tree-data-structure-in-database我创建了序列化程序类

class JsonSerializer(object):
    """A mixin that can be used to mark a SQLAlchemy model class which
    implements a :func:`to_json` method. The :func:`to_json` method is used
    in conjuction with the custom :class:`JSONEncoder` class. By default this
    mixin will assume all properties of the SQLAlchemy model are to be visible
    in the JSON output. Extend this class to customize which properties are
    public, hidden or modified before being being passed to the JSON serializer.
    """

    __json_public__ = None
    __json_hidden__ = None
    __json_modifiers__ = None

    def get_field_names(self):
        for p in self.__mapper__.iterate_properties:
            yield p.key

    def to_json(self):

        field_names = self.get_field_names()

        public = self.__json_public__ or field_names
        hidden = self.__json_hidden__ or []
        modifiers = self.__json_modifiers__ or dict()

        rv = dict()
        for key in public:
            rv[key] = getattr(self, key)
        for key, modifier in modifiers.items():
            value = getattr(self, key)
            rv[key] = modifier(value, self)
        for key in hidden:
            rv.pop(key, None)
        return rv

并将其子类化为我的 Medications 类,根据 class Medications(db.Model, JsonSerializer):

然后我调用 Models.to_json() 来获取我的序列化 JSON 输出,但是,唉,对象是空的:{'parent_id': None, 'type': None, ' children': [], 'name': None, 'id': None

但是,作为测试,如果我创建一个 Flask ReSTLess 端点,按照

manager = flask.ext.restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Medications, methods=['GET'])

我得到以下输出:

"objects": [
    {
      "children": [
        {
          "id": 4, 
          "name": "Child1", 
          "parent_id": 3, 
          "type": "Leaf"
        }, 
        {
          "id": 5, 
          "name": "Child2", 
          "parent_id": 3, 
          "type": "Leaf"
        }
      ], 
      "id": 3, 
      "name": "CardioTest", 
      "parent_id": null, 
      "type": "Parent"
    }, 
    {
      "children": [], 
      "id": 4, 
      "name": "Child1", 
      "parent_id": 3, 
      "type": "Leaf"
    }, 
    {
      "children": [], 
      "id": 5, 
      "name": "Child2", 
      "parent_id": 3, 
      "type": "Leaf"
    }
  ], 

以及一些分页信息。

很好奇为什么我从使用 JsonSerializer 类的方法中得到一个空字典。我会使用 Flask ReSTLess 方法,但由于我将 Flask 用作 wsgi 应用程序,它会搞砸我的端点,此外,输出中不需要带有 children: [] 的节点。

最佳答案

我的问题的解决方案最终是使用 Marshmallow 和嵌套模式(在这篇文章 creating-a-tree-from-self-referential-tables-in-sqlalchemy 的帮助下,ala

# create SQLAlchemy object
record = db.session.query(Medications). \
    options(joinedload_all("children", "children",
                           "children", "children",
                           "children", "children")).first()


class TestSchema(Schema):
    name = fields.Str()
    type = fields.Str()
    id = fields.Int(dump_only=True)
    parent_id = fields.Int(dump_only=True)
    children = fields.Nested('self', many=True)

schema = TestSchema()

result = schema.dump(record)

工作起来非常棒,无需实现递归方法来构建树。

关于python - 来自邻接表的嵌套 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34299680/

相关文章:

python - Pandas 值错误 : 'Date' is not in list

c# - 为什么在使用 .NET Newtonsoft.Json 组件反序列化一些有效的 json 时,我的 POCO 中的所有集合都是空的

python - 如何在一个 Flask 函数中从单个页面获取多个 html 表单

python - Flask 上下文处理器在导入的模板中不起作用

flask - 带有 flask-jwt-extended 的 API 存在身份验证问题?

python - 在 MayaVi 中指定 3D 点的绝对颜色

python - 如何检查 anaconda 软件包是否已正确安装

javascript - 如何获取与另一个给定值匹配的 JSON 对象的键值?

python - 在内存中加载大型字典的巨大内存使用量

python - 包含多个 JSON 文档的文件中的 JSONDecodeError "Expecting property name enclosed in double quotes"