41

mysql クエリの結果を JSON に出力しようとしています。datetime.datetime フィールドのシリアル化に問題があるため、それを行うための小さな関数を作成しました。

def date_handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    else:
        return obj

そして、メインコードで私はただ実行しています:

products_json = []
for code in best_matching_codes:
    cur = db.cursor()
    query = "SELECT * FROM %s WHERE code LIKE '%s'" % (PRODUCTS_TABLE_NAME, product_code)
    cur.execute(query)
    columns = [desc[0] for desc in cur.description]
    rows = cur.fetchall()
    for row in rows:
        products_json.append(dict((k,v) for k,v in zip(columns,row)))   

return json.dumps(products_json, default = date_handler)

しかし、date_handler 関数を書いたので、「ValueError: 循環参照が検出されました」というメッセージが表示されます。

127.0.0.1 - - [10/Jan/2013 00:42:18] "GET /1/product?code=9571%2F702 HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
  File "/Library/Python/2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/pisarzp/Desktop/SusyChoosy/susyAPI/test1.py", line 69, in product_search
return json.dumps(products_json, default = date_handler)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
ValueError: Circular reference detected

私は何を壊しましたか?出力を JSON にシリアル化するより良い方法はありますか?

4

3 に答える 3

25

引数として渡す関数はdefault、モジュールによってネイティブにシリアル化できないオブジェクトに対してのみ呼び出されjsonます。シリアライズ可能なオブジェクトを返すか、TypeError を発生させる必要があります。

バージョンは、修正している型 (日付) でない場合、渡されたのと同じオブジェクトを返します。これが循環参照エラーを引き起こしています (円は によって処理された後、1 つのオブジェクトとそれ自体の間にあるため、誤解を招きますdate_handler)。

date_handlerブロックで例外を発生させるように変更することで、これを修正することができelseます。それでも失敗する可能性がありますが、次のようなコードを使用して、問題の原因となっているデータ構造内のオブジェクトを見つけることができます。

def date_handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    else:
        raise TypeError(
            "Unserializable object {} of type {}".format(obj, type(obj))
        )
于 2013-01-10T05:18:00.230 に答える
2
json.dumps(obj, default=method_name)

「method_name」関数はシリアライズ オブジェクトを返す必要があります。

def method_name(obj):
    data = {
            '__class__': obj.__class__.__name__,
            '__module__': obj.__module__
           }
    data.update(obj.__dict__)
    return data
于 2015-11-02T17:52:12.443 に答える