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