由于使用JDBC连接器进行MySQL查询,我得到了一个结果集。所以我的工作是将结果集转换为JSON格式。这样我就可以将它作为AJAX响应发送到客户端。有人可以解释如何转换为JSON格式,因为我不熟悉Java以及JSON的概念
答案 0 :(得分:14)
很多人都正确地回答了这个问题。但是,我认为我可以使用以下一小段代码为帖子添加更多价值。它使用Apache-DBUtils
和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);
}
答案 1 :(得分:8)
如果您使用的是JSON,我推荐使用Jackson JSON库。
http://wiki.fasterxml.com/JacksonHome
可以在此处找到jar文件:
http://wiki.fasterxml.com/JacksonDownload
以下是我用于将任何结果集转换为Map&lt;&gt;的通用代码或列表&lt;地图&LT;&GT; &GT;使用JacksonJSON将其转换为JSON非常简单(见下文)。
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;
}
在servlet中,我使用com.fasterxml.jackson.databind.ObjectMapper将List转换为JSON,它将Java泛型转换为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);
}
}
}
您可以将参数传递给PreparedStatement,如下所示:
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 = ?";
}
答案 2 :(得分:5)
我使用了Google GSON库,它是mywebapp / WEB-INF / lib文件夹中的一个小型gson-2.2.4.jar 190KB库。 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();
如果你想要键入的JSON键:值对,则有一个writer.value(String,long,integer等)setter。在foreach rsmd循环中执行switch-case并对编号的sql类型使用适当的setter。默认可以使用writer.value(rs.getString(idx))setter。
使用JsonWriter可以有效地编写大型json回复CPU + RAM。您不需要首先循环sqlresultset并在RAM中创建大量List。然后在编写json文档时再次循环列表。这个例子一直流动,http回复被分块,而剩余的数据仍被写入servlet输出。
围绕GSON + Sql结果集创建更高级别的包装器相对容易。 jsp页面可以在编写http回复时使用SqlIterator(sqlquery)方法(.next(),getColumnCount(),getType(idx),. getString(idx),. getLong(idx)...)。它循环原始的sql而没有中间List。这对于较小的应用程序无关紧要,但重度使用的应用程序必须更密切地考虑cpu + ram使用模式。或者更好的做SqlToJson(httpresponse,sqlrs)帮助器然后jsp或servlet代码noice是最小的。
答案 3 :(得分:4)
您可以使用任何JSON库。
以下是此实现,返回一个列表,每个元素都是一个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 :(得分:1)
List<Map<String, Object>>
(每个地图包含一行,列名为键,列内容为值,列表是此类行的列表)答案 5 :(得分:1)
如果你想使用Spring,那很容易:
@RestController
public class MyController
@Autowired
private JdbcTemplate jdbcTemplate;
@RequestMapping("/")
List<Map<String,Object>> getAll() {
return jdbcTemplate.queryForList("select * from my_table");
}
}
在mvc-dispatcher-servlet.xml中,您可以像这样设置JdbcTemplate:
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource">
...data source config...
</property>
</bean>
杰克逊应该在你的类路径中(即Maven依赖)。
答案 6 :(得分:0)
对Java使用jsonlib。迭代结果集并从jsonlib添加所需的属性作为JSONObject
对象。
答案 7 :(得分:0)
在我的应用程序中(浏览器上的MySQL / java servlet / javascript)我使用带有快速stringbuilder方法的字符串函数和一个通用的rs.getObject()。 我认为这是最优雅的工作方式:
mouseDragEvent
答案 8 :(得分:0)
我在这里找到了最佳解决方案。
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.ResultSet;
/**
* Convert a result set into a JSON Array
* @param resultSet
* @return a JSONArray
* @throws Exception
*/
public static JSONArray convertToJSON(ResultSet resultSet)
throws Exception {
JSONArray jsonArray = new JSONArray();
while (resultSet.next()) {
int total_rows = resultSet.getMetaData().getColumnCount();
for (int i = 0; i < total_rows; i++) {
JSONObject obj = new JSONObject();
obj.put(resultSet.getMetaData().getColumnLabel(i + 1)
.toLowerCase(), resultSet.getObject(i + 1));
jsonArray.put(obj);
}
}
return jsonArray;
}
答案 9 :(得分:0)
如果您利用Spring的JDBCTemplate执行存储的函数,该函数将游标作为表项列表返回,并且又希望将其映射为指定bean的列表,那么有最整洁的解决方案: / p>
import com.fasterxml.jackson.databind.ObjectMapper;
...
final static ObjectMapper mapper = new ObjectMapper();
...
<T> List<T> populateExecuteRetrieve(SimpleJdbcCall call, Map inputParameters, Class<T> outputClass) {
List<?> sqlResult;
sqlResult = call.executeFunction(ArrayList.class, parameter);
return sqlResult
.stream()
.map(entry -> mapper.convertValue(entry, outputBeanClass))
.collect(Collectors.toList());
}
不客气!
编码愉快!