我正在尝试将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?
作为default
参数传递的函数将仅对json
模块无法本机序列化的对象调用。它必须返回一个可序列化的对象,或者引发一个TypeError。
若您的版本返回的对象不是您正在修复的类型(日期(,那个么它将返回与您传递的对象相同的对象。这导致了循环参考误差(这是误导性的,因为循环在经过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))
)
与其自己引发TypeError
,不如将调用中继到JSONEncoder
的默认方法:
def date_handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
json.JSONEncoder.default(self,obj)
这也将提高TypeError
,这是一种更好的做法,它允许JSONEncoder
尝试并编码您的方法不能编码的类型。
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
您可以简单地删除dicts、list、tuple中的循环引用,使对象可序列化为