web-dev-qa-db-fra.com

Comment convertir un ensemble de résultats Java en JSON?

J'ai un jeu de résultats à la suite d'une requête MySQL utilisant le connecteur JDBC. Mon travail consiste donc à convertir le jeu de résultats au format JSON. Pour que je puisse l'envoyer au côté client sous forme de réponse AJAX. Quelqu'un peut-il expliquer comment faire la conversion au format JSON car je suis novice en Java et aussi en concept

19
Pramod

Beaucoup de gens ont répondu correctement à la question. Mais, je pense que je peux ajouter plus de valeur à la publication avec le petit extrait de code suivant. Il utilise les bibliothèques Apache-DBUtils et Gson

public static String resultSetToJson(Connection connection, String query) {
        List<Map<String, Object>> 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);
    }
11
phoenix

Si vous utilisez JSON, je recommande la bibliothèque Jackson JSON.

http://wiki.fasterxml.com/JacksonHome

Les fichiers jar peuvent être trouvés ici:

http://wiki.fasterxml.com/JacksonDownload

Voici le code générique que j'utilise pour convertir un jeu de résultats en carte <> ou en liste <Carte <>>. La conversion de cette image en JSON à l'aide de JacksonJSON est assez simple (voir ci-dessous).

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<String, Object> findSingle(Object[] params) throws SQLException {
        List<Map<String, Object>> objects = this.findMultiple(params);

        if (objects.size() != 1) {
            throw new SQLException("Query did not produce one object it produced: " + objects.size() + " objects.");
        }

        Map<String, Object> object = objects.get(0);  //extract only the first item;

        return object;
    }

    public List<Map<String, Object>> 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<Map<String, Object>> getEntitiesFromResultSet(ResultSet resultSet) throws SQLException {
        ArrayList<Map<String, Object>> entities = new ArrayList<>();
        while (resultSet.next()) {
            entities.add(getEntityFromResultSet(resultSet));
        }
        return entities;
    }

    protected Map<String, Object> getEntityFromResultSet(ResultSet resultSet) throws SQLException {
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        Map<String, Object> 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;
}

Dans le servlet, je convertis la liste en JSON à l'aide de com.fasterxml.jackson.databind.ObjectMapper, qui convertit les génériques Java en chaîne JSON. 

    Connection connection = null;
    try {
        connection = DataSourceSingleton.getConnection();
        EntityFactory nutrientEntityFactory = new EntityFactory(connection, NUTRIENT_QUERY_STRING);
        List<Map<String, Object>> 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);
            }
        }
    }

Vous pouvez transmettre des paramètres à PreparedStatement comme ceci:

String name = request.getHeader("name");
EntityFactory entityFactory = new EntityFactory(DataSourceSingleton.getConnection(), QUERY_STRING);
Map<String, Object> object = entityFactory.findSingle(new String[]{name});


private static final String QUERY_STRING = "SELECT NAME, PASSWORD, TOKEN, TOKEN_EXPIRATION FROM USER WHERE NAME = ?";

}

8
Nathaniel Johnson

J'ai utilisé la bibliothèque Google GSON, sa toute petite bibliothèque gson-2.2.4.jar de 190 Ko dans un dossier 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 vous voulez des paires clé/valeur JSON typées, il existe un séparateur writer.value (String, long, integer, etc.). Effectuez une commutation dans le cas d'une boucle foreach rsmd et utilisez le programme de définition approprié pour les types SQL numérotés. La valeur par défaut pourrait utiliser writer.value (rs.getString (idx)).

L’utilisation de JsonWriter permet d’écrire efficacement de grandes répliques json. CPU + RAM. Vous n'avez pas besoin de faire une boucle avec sqlresultset et de créer une liste massive en RAM. Puis bouclez à nouveau la liste pendant la rédaction du document JSON Cet exemple suit son cours, la réponse http est en cours de traitement tandis que les données restantes sont encore écrites dans la sortie du servlet.

Il est relativement facile de créer des utilitaires d’emballage de niveau supérieur autour des résultats GSON + Sql. La page jsp pourrait utiliser les méthodes SqlIterator (sqlquery) (.next (), getColumnCount (), getType (idx), .getString (idx), .getLong (idx) ...) lors de l'écriture de la réponse http. Il boucle le sql d'origine sans liste intermédiaire. Cela n'a pas d'importance pour les petites applications, mais les applications à usage intensif doivent tenir compte de plus près des modèles d'utilisation de cpu + ram. Ou mieux encore, utilisez SqlToJson (httpresponse, sqlrs), puis jsp ou code de servlet est minime.

5
Whome

Vous pouvez utiliser n'importe quelle bibliothèque JSON.

Ce qui suit est une implémentation de ceci, retourne une liste, avec chaque élément un objet 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<JSONObject> getFormattedResult(ResultSet rs) {
    List<JSONObject> resList = new ArrayList<JSONObject>();
    try {
        // get column names
        ResultSetMetaData rsMeta = rs.getMetaData();
        int columnCnt = rsMeta.getColumnCount();
        List<String> columnNames = new ArrayList<String>();
        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;
}
4
coderz
  • Convertir le jeu de résultats en List<Map<String, Object>> (chaque carte contient une ligne avec des noms de colonne sous forme de clés et le contenu de colonne sous forme de valeur, List est une liste de ces lignes)
  • Utilisez la bibliothèque Gson ou Jackson pour convertir cet objet en JSON.
1
U Mad

C'est assez facile si vous voulez utiliser Spring:

@RestController
public class MyController

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @RequestMapping("/")
  List<Map<String,Object>> getAll() {
    return jdbcTemplate.queryForList("select * from my_table");
  }
}

Dans mvc-dispatcher-servlet.xml, vous configureriez votre JdbcTemplate comme ceci:

<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
  <property name="dataSource">
    ...data source config...
  </property>
</bean>

Jackson devrait être dans votre chemin de classe (c'est-à-dire une dépendance Maven).

1
Neil McGuigan

Utilisez jsonlib pour Java. Parcourez le jeu de résultats et ajoutez les propriétés souhaitées sous forme d'objets JSONObject de jsonlib.

0
Mike Thomsen

Dans mes applications (serveur MySQL/Java/javascript sur navigateur), j'utilise une fonction string avec les méthodes fastbuilder string et un générique rs.getObject () . Je pense que c'est le moyen le plus élégant de faire le travail:

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();
}
0
U.Eberle