2013-01-10 23 views
22

私のmysqlクエリの結果をJSONに出力しようとしています。 私はdatetime.datetimeのフィールドをシリアル化に問題があるので、私はそれを行うには小さな関数を書いた:JSONへの出力のシリアライズ - ValueError:循環参照の検出

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にシリアル化するより良い方法はありますか?

+0

products_jsonの印刷出力を取得できますか?私はいくつか日付と価値のキーの間に重複があると思います。それからそれは同様のエラーを得ることができます。 – jinghli

答えて

14

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

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

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)) 
     ) 
8

をTypeError例外を自分で調達するのではなく、あなたはリレーすべきですJSONEncoderのデフォルト・メソッドを呼び出します。

def date_handler(obj): 
    if hasattr(obj, 'isoformat'): 
     return obj.isoformat() 
    else: 
     json.JSONEncoder.default(self,obj) 

また、これはJSONEncoderがあなたの方法ではできない種類を試してみてエンコードすることができます、TypeErrorを発生させ、より良い練習であるだろう。

+2

'NameError:グローバル名 'self'が定義されていません – HereHere

+0

str(obj)を返すようにしてください – GBrian

+0

json内の配列リストに同じ問題があり、変数名を変更してエラーがなくなりました –

0
json.dumps(obj,default = method_name) 

method_name関数は、serializeオブジェクトを返す必要があります。

def method_name(obj): 
    data = {'__class__':obj.__class__.__name__, 
       '__module__':obj.__module__ 
       } 
    data.update(obj.__dict__) 
    return data`#data is dict object in this case