How to serialize SqlAlchemy result to JSON?

后端 未结 27 1483
说谎
说谎 2020-11-22 09:59

Django has some good automatic serialization of ORM models returned from DB to JSON format.

How to serialize SQLAlchemy query result to JSON format?

I tried

相关标签:
27条回答
  • 2020-11-22 10:28

    While the original question goes back awhile, the number of answers here (and my own experiences) suggest it's a non-trivial question with a lot of different approaches of varying complexity with different trade-offs.

    That's why I built the SQLAthanor library that extends SQLAlchemy's declarative ORM with configurable serialization/de-serialization support that you might want to take a look at.

    The library supports:

    • Python 2.7, 3.4, 3.5, and 3.6.
    • SQLAlchemy versions 0.9 and higher
    • serialization/de-serialization to/from JSON, CSV, YAML, and Python dict
    • serialization/de-serialization of columns/attributes, relationships, hybrid properties, and association proxies
    • enabling and disabling of serialization for particular formats and columns/relationships/attributes (e.g. you want to support an inbound password value, but never include an outbound one)
    • pre-serialization and post-deserialization value processing (for validation or type coercion)
    • a pretty straightforward syntax that is both Pythonic and seamlessly consistent with SQLAlchemy's own approach

    You can check out the (I hope!) comprehensive docs here: https://sqlathanor.readthedocs.io/en/latest

    Hope this helps!

    0 讨论(0)
  • 2020-11-22 10:28

    Here is a solution that lets you select the relations you want to include in your output as deep as you would like to go. NOTE: This is a complete re-write taking a dict/str as an arg rather than a list. fixes some stuff..

    def deep_dict(self, relations={}):
        """Output a dict of an SA object recursing as deep as you want.
    
        Takes one argument, relations which is a dictionary of relations we'd
        like to pull out. The relations dict items can be a single relation
        name or deeper relation names connected by sub dicts
    
        Example:
            Say we have a Person object with a family relationship
                person.deep_dict(relations={'family':None})
            Say the family object has homes as a relation then we can do
                person.deep_dict(relations={'family':{'homes':None}})
                OR
                person.deep_dict(relations={'family':'homes'})
            Say homes has a relation like rooms you can do
                person.deep_dict(relations={'family':{'homes':'rooms'}})
                and so on...
        """
        mydict =  dict((c, str(a)) for c, a in
                        self.__dict__.items() if c != '_sa_instance_state')
        if not relations:
            # just return ourselves
            return mydict
    
        # otherwise we need to go deeper
        if not isinstance(relations, dict) and not isinstance(relations, str):
            raise Exception("relations should be a dict, it is of type {}".format(type(relations)))
    
        # got here so check and handle if we were passed a dict
        if isinstance(relations, dict):
            # we were passed deeper info
            for left, right in relations.items():
                myrel = getattr(self, left)
                if isinstance(myrel, list):
                    mydict[left] = [rel.deep_dict(relations=right) for rel in myrel]
                else:
                    mydict[left] = myrel.deep_dict(relations=right)
        # if we get here check and handle if we were passed a string
        elif isinstance(relations, str):
            # passed a single item
            myrel = getattr(self, relations)
            left = relations
            if isinstance(myrel, list):
                mydict[left] = [rel.deep_dict(relations=None)
                                     for rel in myrel]
            else:
                mydict[left] = myrel.deep_dict(relations=None)
    
        return mydict
    

    so for an example using person/family/homes/rooms... turning it into json all you need is

    json.dumps(person.deep_dict(relations={'family':{'homes':'rooms'}}))
    
    0 讨论(0)
  • 2020-11-22 10:29

    You can use introspection of SqlAlchemy as this :

    mysql = SQLAlchemy()
    from sqlalchemy import inspect
    
    class Contacts(mysql.Model):  
        __tablename__ = 'CONTACTS'
        id = mysql.Column(mysql.Integer, primary_key=True)
        first_name = mysql.Column(mysql.String(128), nullable=False)
        last_name = mysql.Column(mysql.String(128), nullable=False)
        phone = mysql.Column(mysql.String(128), nullable=False)
        email = mysql.Column(mysql.String(128), nullable=False)
        street = mysql.Column(mysql.String(128), nullable=False)
        zip_code = mysql.Column(mysql.String(128), nullable=False)
        city = mysql.Column(mysql.String(128), nullable=False)
        def toDict(self):
            return { c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs }
    
    @app.route('/contacts',methods=['GET'])
    def getContacts():
        contacts = Contacts.query.all()
        contactsArr = []
        for contact in contacts:
            contactsArr.append(contact.toDict()) 
        return jsonify(contactsArr)
    
    @app.route('/contacts/<int:id>',methods=['GET'])
    def getContact(id):
        contact = Contacts.query.get(id)
        return jsonify(contact.toDict())
    

    Get inspired from an answer here : Convert sqlalchemy row object to python dict

    0 讨论(0)
提交回复
热议问题