2012-06-04 15 views
6

Estoy intentando devolver una función como esta:¿Cómo puedo configurar la codificación JSON de Pyramid?

@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) 

Debido propia codificación JSON de la pirámide, que está saliendo de doble codificado así:

"{\"color\": \"color\", \"message\": \"message\"}" 

¿Cómo puedo solucionar este problema? Necesito usar el default argument (o equivalente) porque es obligatorio para los tipos personalizados de Mongo.

+4

Este no es un formato extraño. Este es un formato JSON * normal *, usa comillas escapadas. – VisioN

+1

@VisioN: It * is * formato JSON normal ... * para una cadena *. –

+0

¿Por qué no obtengo el error si paso directamente a JSON (sin JSON.dumps)? – zakdances

Respuesta

8

Parece que el diccionario está siendo codificado JSON-dos veces, el equivalente a:

json.dumps(json.dumps({ "color" : "color", "message" : "message" })) 

Tal vez su marco Python automáticamente JSON-codifica el resultado? Tal vez puedas probar:

def returnJSON(color, message=None): 
    return { "color" : "color", "message" : "message" } 

EDIT:

Para utilizar un procesador de pirámide personalizada que genera JSON de la manera deseada, probar este (basado en el renderer docs y la renderer sources).

En el arranque:

from pyramid.config import Configurator 
from pyramid.renderers import JSON 

config = Configurator() 
config.add_renderer('json_with_custom_default', JSON(default=json_util.default)) 

entonces usted tiene un procesador de 'json_with_custom_default' utilizar:

@view_config(route_name='CreateNewAccount', request_method='GET', renderer='json_with_custom_default') 

EDIT 2

Otra opción podría ser para devolver un objeto Response cuales El renderizador no debe modificar. P.ej.

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) 
+0

Eso funciona, como mencioné en la publicación. Sin embargo, necesito usar JSON.dumps porque necesito default = json_util.default para serializar los objetos de Mongo. – zakdances

+2

¿Qué estructura web de Python estás usando? Necesita deshabilitar la codificación JSON automática, o encontrar una manera de modificar la forma en que el marco hace la codificación JSON. – orip

+1

Estoy usando Pyramid. Se establece con un renderizador: @view_config (route_name = 'CreateNewAccount', request_method = 'GET', renderer = 'json') – zakdances

0

Eres dumping the string del objeto Python (diccionario) que le estás proporcionando.

El manual para json.dumps afirma: obj

Serialize a un str formato JSON.

Para convertir desde la cadena, necesitará usar el Python JSON function loads que CARGUE una cadena en un objeto JSON.

Lo que parece que estás tratando de hacer sin embargo, es encode un diccionario de Python para JSON.

def returnJSON(color, message=None): 
    return json.encode({ "color" : color, "message" : message }) 
+0

¿Puedo usar json.encode con default = json_util.default? – zakdances

+0

El problema no son los volcados iniciales. El problema es que está siendo codificado * nuevamente * en el futuro. –

+1

Estoy de acuerdo. Es probable que sea causado por esta línea: @view_config (route_name = 'CreateNewAccount', request_method = 'GET', renderer = 'json') – zakdances

1

No dijiste, pero voy a suponer que sólo está utilizando el módulo estándar json.

El módulo json no define una clase para JSON; usa una Python estándar dict como la representación "nativa" de sus datos. json.dumps() codifica un dict como una cadena JSON; json.loads() toma una cadena JSON y devuelve un dict.

Así que en lugar de hacer esto:

def returnJSON(color, message=None): 
    return json.dumps({ "color" : "color", "message" : "message" }, default=json_util.default) 

Trate de hacer esto:

def returnJSON(color, message=None): 
    return { "color" : "color", "message" : "message" } 

sólo tiene que pasar hacia atrás una llanura dict. Vea cómo le gusta a su aplicación de iPhone.

2

Además de otras respuestas excelentes, me gustaría señalar que si no desea que los datos devueltos por su función de vista se pasen a través de json.dumps, entonces no debería usar renderer = "json" en la configuración de la vista :)

Así que en lugar de

@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) 

sólo puede utilizar

@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 renderizador se acaba de pasar los datos de la cadena devuelta por su función tal cual. Sin embargo, registrar un renderizador personalizado es un enfoque más agradable (vea la respuesta de @ orip)

+0

Esto es cierto y es la solución que estoy usando ahora. Tendré que esperar hasta que se libere Pyramid 1.4 para usar un renderizador personalizado. – zakdances

+0

Creo que ha leído mal la documentación: el registro de renderizadores personalizados ha estado disponible en Pyramid desde hace mucho tiempo, estoy usando un procesador personalizado en una aplicación desde que Pyramid se llamaba repoze.bfg. http://pyramid.readthedocs.org/en/latest/narr/renderers.html#adding-a-new-renderer – Sergey

+0

Debería haber sido más específico ... Me refiero a que la función JSON() para crear parámetros de renderizado solo tiene sido agregado en 1.4 – zakdances

Cuestiones relacionadas