平面实施
你可以使用如下形式:
from sqlalchemy.ext.declarative import Declarativemetaclass AlchemyEnprer(json.JSONEnprer): def default(self, obj): if isinstance(obj.__class__, Declarativemeta): # an SQLAlchemy class fields = {} for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']: data = obj.__getattribute__(field) try: json.dumps(data) # this will fail on non-encodable values, like other classes fields[field] = data except TypeError: fields[field] = None # a json-encodable dict return fields return json.JSONEnprer.default(self, obj)然后使用以下命令转换为JSON:
c = YourAlchemyClass()print json.dumps(c, cls=AlchemyEnprer)
它将忽略不可编码的字段(将它们设置为“无”)。
它不会自动展开关系(因为这可能导致自我引用,并永远循环)。
递归的非循环实现
但是,如果你希望永久循环,则可以使用:
from sqlalchemy.ext.declarative import Declarativemetadef new_alchemy_enprer(): _visited_objs = [] class AlchemyEnprer(json.JSONEnprer): def default(self, obj): if isinstance(obj.__class__, Declarativemeta): # don't re-visit self if obj in _visited_objs: return None _visited_objs.append(obj) # an SQLAlchemy class fields = {} for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']: fields[field] = obj.__getattribute__(field) # a json-encodable dict return fields return json.JSONEnprer.default(self, obj) return AlchemyEnprer然后使用以下代码编码对象:
print json.dumps(e, cls=new_alchemy_enprer(), check_circular=False)
这将对所有子项,所有子项以及所有子项进行编码。基本上,可能对整个数据库进行编码。当它到达之前已编码的内容时,会将其编码为“无”。
递归(可能是循环的)选择性实现
另一种可能更好的选择是能够指定要扩展的字段:
def new_alchemy_enprer(revisit_self = False, fields_to_expand = []): _visited_objs = [] class AlchemyEnprer(json.JSONEnprer): 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']: val = obj.__getattribute__(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] = None continue fields[field] = val # a json-encodable dict return fields return json.JSONEnprer.default(self, obj) return AlchemyEnprer你现在可以通过以下方式调用它:
print json.dumps(e, cls=new_alchemy_enprer(False, ['parents']), check_circular=False)
例如,仅扩展名为“父母”的SQLAlchemy字段。



