การใช้งานแบน
คุณสามารถใช้สิ่งนี้:
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)
เมื่อต้องการขยายเขตข้อมูล SQLAlchemy ที่เรียกว่า 'parent' เท่านั้น