I am using MongoEngine's to_json
method on an object I wish to render in a json-rendered Pyarmid page. I've done lots of json rendering in Pyramid, but not with MongoEngine. MongoEngine's to_json
method simple calls json_util.dumps
. It all works fine in Python. The problem is that when Pyramid renders the page, it is rendered like this:
{
"0": "\"",
"1": "{",
"2": "\\",
"3": "\"",
"4": "_", etc...
However, the json dump looks ok in Python, before it is rendered:
'{"_id": {"$oid": "4ebca43ccc7a67085b000000"}, "created": {"$date": 1346419407715}, "modified": {"$date": 1403757381829}, "modified_by": {"$oid": "4ebca43ccc7a67085b000000"}, "email": etc...
As has been suggested in the comments, it seems like the json is being jsonified more than once, but I can't figure out where.
I pick up the User
object from the database and attach it every request:
def get_user(request):
return User.objects(id=ObjectId(authenticated_userid(request))).first()
config.add_request_method(get_user, 'user', reify=True)
I return the user as per request:
@view_config(route_name='api.user', permission='authenticated', renderer='json')
def user_vc(request):
response = request.response
_id = request.matchdict['id']
if _id == 'session':
user = request.user
if not user:
response.status = 403
return response
else:
print user # user object as expected (not json)
return user
I have a custom adapter to handle the User
object:
# custom json adapters
custom_json = JSON()
def user_adapter(obj, request):
print obj.to_json() # the json looks ok here
return obj.to_json()
custom_json.add_adapter(User, user_adapter)
config.add_renderer('json', custom_json)
I am not doing any other jsonification myself, apart from the adapter above. So what is?? Any help would be great.
Thanks to a comment by @AnttiHappala above, I found the problem. MongoEngine's to_json
method converts objects to a jsonified string. However, Pyramid needs a json data structure. So, to fix it, I added the following function to my custom renderer:
def render_to_json(obj):
return json.loads(obj.to_json())
def user_adapter(obj, request):
return render_to_json(obj)
custom_json.add_adapter(User, user_adapter)
I can now add a custom renderer for my other MongoEngine objects and return them natively.