将输出序列化为JSON-ValueError:检测到循环引用 [英] Serializing output to JSON - ValueError: Circular reference detected

查看:197
本文介绍了将输出序列化为JSON-ValueError:检测到循环引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将mysql查询的结果输出到JSON. 我在序列化datetime.datetime字段时遇到问题,所以我写了一个小函数来做到这一点:

I'm trying to output results of my mysql query to JSON. I have problem with serializing datetime.datetime field, so I wrote small function to do that:

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

然后在主代码中我正在运行:

and then in main code I'm just running:

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:检测到循环引用"

However, since I wrote date_handler function, I'm getting "ValueError: Circular reference detected"

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?

What did I break? Is there a better way to serialize output to JSON?

推荐答案

作为default参数传递的函数将仅针对不能由json模块本地化的对象调用.它必须返回一个可序列化的对象,或引发TypeError.

The function you pass as the default argument will only be called for objects that are not natively serializable by the json module. It must return a serializable object, or raise a TypeError.

您的版本返回的是与您传递的对象相同的对象,如果它不是您要固定的一种类型(日期).这会导致循环参考误差(这是令人误解的,因为在经过date_handler处理后,该圆形位于一个对象与其自身之间).

Your version returns the same object you were passed if it's not of the one type you're fixing (dates). That is causing the circular reference error (which is misleading, since the circle is between one object and itself after being processed by date_handler).

您可以通过更改date_handler以在其else块中引发异常来开始解决此问题.那仍然可能会失败,但是您可以使用以下代码找出数据结构中的哪个对象,该对象导致了问题:

You can start to fix this by changing date_handler to raise an exception in its else block. That will still probably fail, but you can probably then find out what object it is that is in your data structure causing the problem using code like this:

def date_handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    else:
        raise TypeError(
            "Unserializable object {} of type {}".format(obj, type(obj))
        )

这篇关于将输出序列化为JSON-ValueError:检测到循环引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆