¿Cómo convertir un conjunto de resultados de Java a JSON?

Tengo un conjunto de resultados como resultado de una consulta MySQL utilizando el conector JDBC. Así que mi trabajo es convertir el conjunto de resultados en un formato JSON. Para poder enviarlo al cliente como respuesta AJAX. ¿Puede alguien explicar cómo hacer la conversión al formato JSON ya que soy nuevo en Java y también en el concepto de JSON?

Muchas personas respondieron la pregunta correctamente. Pero, creo que puedo agregar más valor a la publicación con el siguiente pequeño fragmento de código. Utiliza Apache-DBUtils y la biblioteca Gson .

 public static String resultSetToJson(Connection connection, String query) { List> listOfMaps = null; try { QueryRunner queryRunner = new QueryRunner(); listOfMaps = queryRunner.query(connection, query, new MapListHandler()); } catch (SQLException se) { throw new RuntimeException("Couldn't query the database.", se); } finally { DbUtils.closeQuietly(connection); } return new Gson().toJson(listOfMaps); } 

Si está utilizando JSON, recomiendo la biblioteca Jackson JSON.

http://wiki.fasterxml.com/JacksonHome

Los archivos jar se pueden encontrar aquí:

http://wiki.fasterxml.com/JacksonDownload

Aquí está el código genérico que utilizo para convertir cualquier conjunto de resultados en un Mapa <> o una Lista > Convertir esto a JSON usando JacksonJSON es bastante sencillo (Ver más abajo).

 package com.naj.tmoi.entity; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class EntityFactory { public EntityFactory(Connection connection, String queryString) { this.queryString = queryString; this.connection = connection; } public Map findSingle(Object[] params) throws SQLException { List> objects = this.findMultiple(params); if (objects.size() != 1) { throw new SQLException("Query did not produce one object it produced: " + objects.size() + " objects."); } Map object = objects.get(0); //extract only the first item; return object; } public List> findMultiple(Object[] params) throws SQLException { ResultSet rs = null; PreparedStatement ps = null; try { ps = this.connection.prepareStatement(this.queryString); for (int i = 0; i < params.length; ++i) { ps.setObject(1, params[i]); } rs = ps.executeQuery(); return getEntitiesFromResultSet(rs); } catch (SQLException e) { throw (e); } finally { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } } } protected List> getEntitiesFromResultSet(ResultSet resultSet) throws SQLException { ArrayList> entities = new ArrayList<>(); while (resultSet.next()) { entities.add(getEntityFromResultSet(resultSet)); } return entities; } protected Map getEntityFromResultSet(ResultSet resultSet) throws SQLException { ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); Map resultsMap = new HashMap<>(); for (int i = 1; i <= columnCount; ++i) { String columnName = metaData.getColumnName(i).toLowerCase(); Object object = resultSet.getObject(i); resultsMap.put(columnName, object); } return resultsMap; } private final String queryString; protected Connection connection; } 

En el servlet, convierto la lista en JSON utilizando com.fasterxml.jackson.databind.ObjectMapper, que convierte Java Generics en una cadena JSON.

  Connection connection = null; try { connection = DataSourceSingleton.getConnection(); EntityFactory nutrientEntityFactory = new EntityFactory(connection, NUTRIENT_QUERY_STRING); List> nutrients = nutrientEntityFactory.findMultiple(new Object[]{}); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(nutrients); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(json); } catch (SQLException e) { throw new ServletException(e); } finally { if (connection != null) { try { connection.close(); } catch (SQLException e) { throw new ServletException(e); } } } 

Puede pasar Parámetros al PreparedStatement así:

 String name = request.getHeader("name"); EntityFactory entityFactory = new EntityFactory(DataSourceSingleton.getConnection(), QUERY_STRING); Map object = entityFactory.findSingle(new String[]{name}); private static final String QUERY_STRING = "SELECT NAME, PASSWORD, TOKEN, TOKEN_EXPIRATION FROM USER WHERE NAME = ?"; 

}

He usado la biblioteca Google GSON, su pequeña biblioteca gson-2.2.4.jar 190KB en una carpeta mywebapp / WEB-INF / lib. http://code.google.com/p/google-gson/

 import com.google.gson.stream.JsonWriter; --- httpres.setContentType("application/json; charset=UTF-8"); httpres.setCharacterEncoding("UTF-8"); JsonWriter writer = new JsonWriter(new OutputStreamWriter(httpres.getOutputStream(), "UTF-8")); while(rs.next()) { writer.beginObject(); // loop rs.getResultSetMetadata columns for(int idx=1; idx<=rsmd.getColumnCount(); idx++) { writer.name(rsmd.getColumnLabel(idx)); // write key:value pairs writer.value(rs.getString(idx)); } writer.endObject(); } writer.close(); httpres.getOutputStream().flush(); 

Si quiere tipear clave JSON: pares de valores hay un setteador writer.value (String, long, integer, etc.). Haga switch-case dentro del bucle foreach rsmd y use el setter apropiado para los tipos sql numerados. El valor predeterminado podría usar writer.value (rs.getString (idx)) setter.

El uso de JsonWriter permite escribir grandes respuestas json CPU + RAM de manera efectiva. No es necesario bucle sqlresultset primero y crear una lista masiva en la memoria RAM. Luego, vuelva a enlistar la lista mientras escribe el documento json. Este ejemplo fluye a medida que avanza, la respuesta http se fragmenta mientras que los datos restantes se escriben en la salida del servlet.

Es relativamente fácil crear herramientas de envoltura de nivel superior alrededor del conjunto de resultados GSON + Sql. La página jsp podría usar los métodos SqlIterator (sqlquery) (.next (), getColumnCount (), getType (idx), .getString (idx), .getLong (idx) ...) al escribir http reply. Bucles el sql original sin lista intermedia. Esto no importa para aplicaciones más pequeñas, pero las aplicaciones de uso intensivo deben considerar los patrones de uso de cpu + ram más de cerca. O mejor aún, SqlToJson (httpresponse, sqlrs) helper y jsp o servlet code noice son mínimos.

Puede usar cualquier biblioteca JSON.

La siguiente es una implementación de esto, devuelve una lista, con cada elemento un objeto JSON:

 /* * Convert ResultSet to a common JSON Object array * Result is like: [{"ID":"1","NAME":"Tom","AGE":"24"}, {"ID":"2","NAME":"Bob","AGE":"26"}, ...] */ public static List getFormattedResult(ResultSet rs) { List resList = new ArrayList(); try { // get column names ResultSetMetaData rsMeta = rs.getMetaData(); int columnCnt = rsMeta.getColumnCount(); List columnNames = new ArrayList(); for(int i=1;i<=columnCnt;i++) { columnNames.add(rsMeta.getColumnName(i).toUpperCase()); } while(rs.next()) { // convert each object to an human readable JSON object JSONObject obj = new JSONObject(); for(int i=1;i<=columnCnt;i++) { String key = columnNames.get(i - 1); String value = rs.getString(i); obj.put(key, value); } resList.add(obj); } } catch(Exception e) { e.printStackTrace(); } finally { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return resList; } 
  • Convierte los resultados en List> (cada mapa contiene una fila con nombres de columna como claves y contenido de columna como valor, List es una lista de tales filas)
  • Use la biblioteca Gson o Jackson para convertir este objeto en JSON.

Use jsonlib para Java. Itera sobre el conjunto de resultados y agrega las propiedades que deseas como objetos JSONObject de jsonlib.

Es bastante fácil si quieres usar Spring:

 @RestController public class MyController @Autowired private JdbcTemplate jdbcTemplate; @RequestMapping("/") List> getAll() { return jdbcTemplate.queryForList("select * from my_table"); } } 

En mvc-dispatcher-servlet.xml, configuraría su JdbcTemplate de la siguiente manera:

   ...data source config...   

Jackson debería estar en su classpath (es decir, una dependencia de Maven).

Dentro de mis aplicaciones (MySQL / java servlet / javascript en el navegador) utilizo una función de cadena con los métodos rápidos de stringbuilder y un rs.getObject genérico (). Creo que es la forma más elegante de hacer el trabajo:

 public String rStoJason(ResultSet rs) throws SQLException { if(rs.first() == false) {return "[]";} else {rs.beforeFirst();} // empty rs StringBuilder sb=new StringBuilder(); Object item; String value; java.sql.ResultSetMetaData rsmd = rs.getMetaData(); int numColumns = rsmd.getColumnCount(); sb.append("[{"); while (rs.next()) { for (int i = 1; i < numColumns + 1; i++) { String column_name = rsmd.getColumnName(i); item=rs.getObject(i); if (item !=null ) {value = item.toString(); value=value.replace('"', '\'');} else {value = "null";} sb.append("\"" + column_name+ "\":\"" + value +"\","); } //end For = end record sb.setCharAt(sb.length()-1, '}'); //replace last comma with curly bracket sb.append(",{"); } // end While = end resultset sb.delete(sb.length()-3, sb.length()); //delete last two chars sb.append("}]"); return sb.toString(); }