평평한 구현
다음과 같은 것을 사용할 수 있습니다.
from sqlalchemy.ext.declarative import DeclarativeMeta
class AlchemyEncoder(json.JSONEncoder):
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.JSONEncoder.default(self, obj)
다음을 사용하여 JSON으로 변환하십시오.
c = YourAlchemyClass()
print json.dumps(c, cls=AlchemyEncoder)
인코딩 할 수없는 필드는 무시합니다 ( '없음'으로 설정).
자동 확장 관계는 아닙니다 (자기 참조로 이어질 수 있고 영원히 반복 될 수 있기 때문에).
재귀적인 비 원형 구현
그러나 영원히 반복하려면 다음을 사용할 수 있습니다.
from sqlalchemy.ext.declarative import DeclarativeMeta
def new_alchemy_encoder():
_visited_objs = []
class AlchemyEncoder(json.JSONEncoder):
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.JSONEncoder.default(self, obj)
return AlchemyEncoder
그런 다음 다음을 사용하여 객체를 인코딩하십시오.
print json.dumps(e, cls=new_alchemy_encoder(), check_circular=False)
이것은 모든 어린이와 모든 어린이와 모든 어린이를 인코딩합니다 ... 기본적으로 전체 데이터베이스를 잠재적으로 인코딩합니다. 이전에 인코딩 된 항목에 도달하면 '없음'으로 인코딩합니다.
재귀적이고 순환 가능하며 선택적 구현
또 다른 대안은 아마도 확장하려는 필드를 지정할 수 있다는 것입니다.
def new_alchemy_encoder(revisit_self = False, fields_to_expand = []):
_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']:
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.JSONEncoder.default(self, obj)
return AlchemyEncoder
이제 다음과 같이 호출 할 수 있습니다.
print json.dumps(e, cls=new_alchemy_encoder(False, ['parents']), check_circular=False)
예를 들어 'parents'라는 SQLAlchemy 필드 만 확장합니다.