Estás leyendo:
Informática

Grails; Convert a generic projection resultSet in a JSON list of maps



A few time ago We had had to send a concrete projection (one column) from one entity’s model to the connected view in a grails web applicaton for achieve autocompleted controls in the web form.

As well as we had selected grails framework to develop the web project, We also had selected jquery to build a rich user interface. Obviously, the data exchange format between model ans view is JSON. So, our need was to convert a GORM-hibernate projection to a well formed JSON data set.

First, We have builded a Service with the goal of manage the layers communication and we had injected the converters.JSON grails plugin to facility a easy management of created JSON objects. The initial task went the creation of the solution to the more easy case: One JSON list from a unique column:

/**
    Achieve a list with all the values from a Entity's field
    Luis Torres. EBD-CSIC
    */       
    def listadoColumna={field,entity->

        def lista=entity.withCriteria{
            projections{
                distinct(field)
            }
            and
            //Hay que eliminar los nulos de la lista pq falla el autocomplete de jquery
            {isNotNull(field)}
            order(field,"asc")
        }
        def listaJSON=(lista as JSON).toString()
        return listaJSON
    }

Easy,isn’t It? Clearly, Groovy-GORM language simplify our life and help us to a easy way of code😉

The next step went a few more complicated: How to create a “maps JSON” list from a anonymous projection? To solve this question We had thinked to send a list of separated titles and another list with the data set created by the GORM projection request like functions parameters to a closure.

    /**
    Function for iterate over a list of list and convert It to a list of maps
    Luis Torres. EBD-CSIC
    */   
    def listOfMaps2JSON(List lista,List fieldTitles){

        def tupla=[]
        lista.each(){row->
            //For each row, It define a map object
            def mapa=[:]
            row.eachWithIndex(){item,i->
                //For each item of the row, It add a value into the map object
                mapa.put(fieldTitles[i],item)                   
            }
            //Once is finished the items addition into th map, He is added to tupla list like as item
            tupla.add(mapa)
        }
        def listaJSON=tupla.encodeAsJSON()
        return listaJSON
    }

Here, the the icing on the cake is the “nested closures” solution to iterate over every list item, and put its subitems to a map who was created at every iteration. The JSON list consequence was trivial.

The elegance of Groovy solution is fantastic: only 10 codelines, brackets included, to obtain a piece of functional (and not trivial) code. I love It!

We still need a little function to send to listOfMaps2JSON the arguments:

    /**
    Achieve a list of list from all values from a Entity projection 
    defined in a list of fields
    Luis Torres. EBD-CSIC
    */       
    def listadoTuplas={fields,entity->

        def lista=entity.withCriteria{
            projections{
                fields.each{field->                  
                    property(field)                               
//                    and
//                    {isNotNull(field)}
                }               
            }
            order(fields[0],"asc")
        }   
        //Eliminate the duplicate entries of resultSet
        def lista2=lista.unique()

        return listOfMaps2JSON(lista2,fields)
    }

The Criteria is similar to listadoColumnas() criteria, but notice in this case the IsNotNull filter has been eliminated: the cause is the goal previously cited, because We should want is a “tuple” list for autocompleted webcontrols sources drawing the connection between the columns of a tuple: It belonging to the same object.

The complete Service code is:

import grails.converters.JSON

class JsHandlerService {

    /**
    Achieve a list with all the values from a Entity's field
    Luis Torres. EBD-CSIC
    */       
    def listadoColumna={field,entity->

        def lista=entity.withCriteria{
            projections{
                distinct(field)
            }
            and
            //Hay que eliminar los nulos de la lista pq falla el autocomplete de jquery
            {isNotNull(field)}
            order(field,"asc")
        }
        def listaJSON=(lista as JSON).toString()
        return listaJSON
    }

    /**
    Achieve a list of list from all values from a Entity projection 
    defined in a list of fields
    Luis Torres. EBD-CSIC
    */       
    def listadoTuplas={fields,entity->

        def lista=entity.withCriteria{
            projections{
                fields.each{field->                  
                    property(field)                               
//                    and
//                    {isNotNull(field)}
                }               
            }
            order(fields[0],"asc")
        }   
        //Eliminate the duplicate entries of resultSet
        def lista2=lista.unique()

        return listOfMaps2JSON(lista2,fields)
    }

    /**
    Function for iterate over a list of list and convert It to a list of maps
    Luis Torres. EBD-CSIC
    */   
    def listOfMaps2JSON(List lista,List fieldTitles){

        def tupla=[]
        lista.each(){row->
            //For each row, It define a map object
            def mapa=[:]
            row.eachWithIndex(){item,i->
                //For each item of the row, It add a value into the map object
                mapa.put(fieldTitles[i],item)                   
            }
            //Once is finished the items addition into th map, He is added to tupla list like as item
            tupla.add(mapa)
        }
        def listaJSON=tupla.encodeAsJSON()
        return listaJSON
    }  
}

Cheers squids!

Discussion

One thought on “Grails; Convert a generic projection resultSet in a JSON list of maps

  1. RIP English.. thanks for the info tho

    Posted by Anonymous | 8 February, 2015, 17:10

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Lo leyeron y comentaron

Top Clicks

  • None

Flickr Photos







More Photos
%d bloggers like this: