2012-03-09 21 views
17

Utilizo el siguiente código para representar datos en formato JSON.Rendering JSON en grises

render(contentType:"text/json") { 
    results = array { 
     db.eachRow(query) { row -> 
      def rs = row.toRowResult() 
      def a = b(rs.name,c,d) 
      aMap.put("A",a) 
      pair(aMap) 
     } 
    } 
    if (results) { 
     status = "OK" 
    } 
    else { 
     status ="Nothing present" 
    } 
} 

El código anterior genera JSON en el siguiente formato

{ 
    "results": [ 
     {"A":"value1"}, 
     {"A":"value2"}, 
     ................... 
     {"A":"valuen"} 
    ], 
    "status":"OK" 
} 

Como u ver anterior, los datos se representa como un matriz de objetos. ¿Hay alguna manera de que pueda representar los datos de resultados como una matriz de elementos? Al igual que

{ 
    "results": [ 
     "value1", 
     "value2", 
     ................... 
     "valuen" 
    ], 
    "status":"OK" 
} 

Respuesta

35

La forma en que se está construyendo el objeto JSON es bastante oscura. Lo que me gusta hacer para representar las respuestas JSON en griales es crear un mapa o una lista en groovy y luego usar el método render solo para convertirlo a JSON.

Haciendo la transformación de los rowResult 's en el interior del método render hace que sea muy confuso, yo prefiero ir para algo como esto

def results = db.rows(query).collect { rowResult -> 
    b(rowResult.name, c, d) 
} 
render(contentType: 'text/json') {[ 
    'results': results, 
    'status': results ? "OK" : "Nothing present" 
]} 

Creo que es más fácil de leer, y aún más corto. Este fragmento obtiene el resultado deseado: no hay objetos dentro de la matriz results, solo cadenas.

Tenga en cuenta el uso de rows, que devuelve una lista de RowResult, eliminando la necesidad de obtenerlo de ResultSet. La lista se usa para recopilar el valor transformado a llamando al b en el nombre de cada fila. La recopilación de los elementos no implica la creación de un mapa (como en el JSON { "A":"value1"} que estaba recibiendo), exactamente el mismo @ will-buck logrado con el operador << en una nueva lista vacía.

Todo lo que hacemos con el método render está declarando el tipo text/json contenido y pasándolo a un mapa literal que contiene las claves results y status, que desea escribir en la respuesta. El operador condicional se usa para determinar de manera concisa el estado. También podría usarse así, mediante el convertidor JSON @ will-buck también mencionado:

def responseData = [ 
    'results': results, 
    'status': results ? "OK" : "Nothing present" 
] 
render responseData as JSON 
+1

Me gusta su último fragmento de código mejor que el primero. Probablemente sea más amigable con los depuradores también. – epidemian

+0

Sí, ese convertidor JSON es definitivamente el camino a seguir :) –

+1

Tiene problemas con su último fragmento en Grails 2.0. La respuesta se representa como texto encerrado en '{}'. – raffian

4

Sólo fuera por un poco :) sólo tiene que cambiar

aMap.put("A", a) 

a ser una colección o una lista, en lugar de un mapa. algo así como

def aList = [] 
aList << a 

¡Le conseguirá lo que quiera!

Como nota al margen, hay un convertidor JSON en los griales que hará esa construcción de cuerdas para usted. Mírelo here