How to serialize SqlAlchemy result to JSON?

后端 未结 27 1495
说谎
说谎 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:22

    I know this is quite an older post. I took solution given by @SashaB and modified as per my need.

    I added following things to it:

    1. Field ignore list: A list of fields to be ignored while serializing
    2. Field replace list: A dictionary containing field names to be replaced by values while serializing.
    3. Removed methods and BaseQuery getting serialized

    My code is as follows:

    def alchemy_json_encoder(revisit_self = False, fields_to_expand = [], fields_to_ignore = [], fields_to_replace = {}):
       """
       Serialize SQLAlchemy result into JSon
       :param revisit_self: True / False
       :param fields_to_expand: Fields which are to be expanded for including their children and all
       :param fields_to_ignore: Fields to be ignored while encoding
       :param fields_to_replace: Field keys to be replaced by values assigned in dictionary
       :return: Json serialized SQLAlchemy object
       """
       _visited_objs = []
       class AlchemyEncoder(json.JSONEncoder):
          def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if revisit_self:
                    if obj in _visited_objs:
                        return None
                    _visited_objs.append(obj)
    
                # go through each field in this SQLalchemy class
                fields = {}
                for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and x not in fields_to_ignore]:
                    val = obj.__getattribute__(field)
                    # is this field method defination, or an SQLalchemy object
                    if not hasattr(val, "__call__") and not isinstance(val, BaseQuery):
                        field_name = fields_to_replace[field] if field in fields_to_replace else field
                        # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                        if isinstance(val.__class__, DeclarativeMeta) or \
                                (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
                            # unless we're expanding this field, stop here
                            if field not in fields_to_expand:
                                # not expanding this field: set it to None and continue
                                fields[field_name] = None
                                continue
    
                        fields[field_name] = val
                # a json-encodable dict
                return fields
    
            return json.JSONEncoder.default(self, obj)
       return AlchemyEncoder
    

    Hope it helps someone!

提交回复
热议问题