I'm trying to return a function like this:
@view_config(route_name='CreateNewAccount', request_method='GET', renderer='json')
def returnJSON(color, message=None):
return json.dumps({ "color" : "color", "message" : "message" }, default=json_util.default)
Because of Pyramid's own JSON encoding, it's coming out double-encoded like this:
"{\"color\": \"color\", \"message\": \"message\"}"
How can I fix this? I need to use the default
argument (or equivalent) because it's required for Mongo's custom types.
It seems like the dictionary is being JSON-encoded twice, the equivalent of:
json.dumps(json.dumps({ "color" : "color", "message" : "message" }))
Perhaps your Python framework automatically JSON-encodes the result? Try this instead:
def returnJSON(color, message=None):
return { "color" : "color", "message" : "message" }
EDIT:
To use a custom Pyramid renderer that generates JSON the way you want, try this (based on the renderer docs and the renderer sources).
In startup:
from pyramid.config import Configurator
from pyramid.renderers import JSON
config = Configurator()
config.add_renderer('json_with_custom_default', JSON(default=json_util.default))
Then you have a 'json_with_custom_default' renderer to use:
@view_config(route_name='CreateNewAccount', request_method='GET', renderer='json_with_custom_default')
EDIT 2
Another option could be to return a Response
object which he renderer shouldn't modify. E.g.
from pyramid.response import Response
def returnJSON(color, message):
json_string = json.dumps({"color": color, "message": message}, default=json_util.default)
return Response(json_string)
In addition to other excellent answers, I'd like to point out that if you don't want the data returned by your view function to be passed through json.dumps then you should not use renderer="json" in the view configuration :)
So instead of
@view_config(route_name='CreateNewAccount', request_method='GET', renderer='json')
def returnJSON(color, message=None):
return json.dumps({ "color" : "color", "message" : "message" }, default=json_util.default)
you can just use
@view_config(route_name='CreateNewAccount', request_method='GET', renderer='string')
def returnJSON(color, message=None):
return json.dumps({ "color" : "color", "message" : "message" }, default=json_util.default)
string
renderer will just pass the string data returned by your function as-is. However, registering a custom renderer is a nicer approach (see @orip's answer)
You didn't say, but I will assume you are just using the standard json
module.
The json
module doesn't define a class for JSON; it uses a standard Python dict
as the "native" representation of your data. json.dumps()
encodes a dict
as a JSON string; json.loads()
takes a JSON string and gives back a dict
.
So instead of doing this:
def returnJSON(color, message=None):
return json.dumps({ "color" : "color", "message" : "message" }, default=json_util.default)
Try doing this:
def returnJSON(color, message=None):
return { "color" : "color", "message" : "message" }
Just pass back a plain dict
. See how your iPhone app likes this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With