[解決済み】SqlAlchemyの結果をJSONにシリアライズする方法は?
質問
Django は、DB から返された ORM モデルを JSON 形式に自動シリアライズするいくつかの良い機能を持っています。
SQLAlchemy のクエリ結果を JSON 形式にシリアライズするには?
試しに
jsonpickle.encode
が、クエリオブジェクト自体をエンコードしてしまいます。
試しに
json.dumps(items)
を返します。
TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable
SQLAlchemyのORMオブジェクトをJSON /XMLにシリアライズするのはそんなに難しいのでしょうか?デフォルトのシリアライザはないのでしょうか?最近、ORM のクエリ結果をシリアライズするのは、とても一般的なタスクです。
必要なのは、SQLAlchemy のクエリ結果を JSON または XML データとして返すことです。
SQLAlchemyオブジェクトのクエリ結果をJSON/XML形式で、javascriptデータグリッド(JQGrid http://www.trirand.com/blog/ )
解決方法は?
フラットな実装
このようなものを使うことができます。
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)
エンコードできないフィールドは無視されます('None'に設定してください)。
リレーションを自動展開しない(自己参照になり、永久にループする可能性があるため)。
再帰的で非循環的な実装
しかし、もし永遠にループしたいのであれば、次のような方法がある。
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 の 'parents' というフィールドだけを展開するためなど。
関連
-
Pythonの画像ファイル処理用ライブラリ「Pillow」(グラフィックの詳細)
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み] 正しいJSONコンテンツタイプは何ですか?
-
[解決済み] JSONでコメントを使用することはできますか?
-
[解決済み] プログラムの実行やシステムコマンドの呼び出しはどのように行うのですか?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] cURLでJSONデータをPOSTするにはどうすればよいですか?
-
[解決済み] JavaScriptでJSONをきれいに印刷する
-
[解決済み] Microsoft JSONの日付はどのようにフォーマットするのですか?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonの非常に便利な2つのデコレーターを解説
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
Pythonを使って簡単なzipファイルの解凍パスワードを手作業で解く
-
Pythonショートビデオクローラーチュートリアル
-
FacebookオープンソースワンストップサービスpythonのタイミングツールKats詳細
-
[解決済み】ImportError: sklearn.cross_validation という名前のモジュールがない。
-
[解決済み】なぜ「LinAlgError: Grangercausalitytestsから「Singular matrix」と表示されるのはなぜですか?
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】「SyntaxError.Syntax」は何ですか?Missing parentheses in call to 'print'」はPythonでどういう意味ですか?
-
[解決済み] FlaskでSQLAlchemyの結果セットをjsonifyする [重複].