У меня есть набор результатов в результате запроса MySQL с использованием JDBC-коннектора. Поэтому моя задача - преобразовать набор результатов в формат JSON. Чтобы я мог отправить его клиенту как ответ AJAX. Может кто-нибудь объяснить, как сделать преобразование в формат JSON, поскольку я новичок в Java, а также в концепции JSON
Как преобразовать набор результатов Java в JSON?
Ответ 1
Многие люди правильно ответили на вопрос. Но, я думаю, я могу добавить больше пользы в сообщение со следующим небольшим фрагментом кода. Он использует библиотеки 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);
}
Ответ 2
Если вы используете JSON, я рекомендую библиотеку Jackson JSON.
http://wiki.fasterxml.com/JacksonHome
Файлы jar можно найти здесь:
http://wiki.fasterxml.com/JacksonDownload
Вот общий код, который я использую для преобразования любого набора результатов в Map < > или List < Map < → Преобразование этого в JSON с использованием JacksonJSON довольно прямолинейно (см. Ниже).
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;
}
В сервлете я конвертирую List в JSON с помощью com.fasterxml.jackson.databind.ObjectMapper, который преобразует Java Generics в строку 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 = ?";
}
Ответ 3
Я использовал библиотеку Google GSON, ее одну крошечную библиотеку 190 kB gson-2.2.4.jar в папке 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();
Если вы хотите ввести пары JSON key: value, существуют установщики writer.value(String, long, integer и т.д.). Сделайте переключатель в пределах цикла foreach rsmd и используйте соответствующий наборщик для пронумерованных типов sql. По умолчанию может использоваться set.setue(rs.getString(idx)).
Использование JsonWriter позволяет эффективно обрабатывать большие json-ответы CPU + RAM. Вам не нужно сначала зацикливать sqlresultset и создать массивный список в ОЗУ. Затем снова запустите список циклов при написании документа json. Этот пример протекает по мере того, как он идет, HTTP-ответ разбивается, а оставшиеся данные все еще записываются на вывод сервлета.
Относительно легко создавать утилиты обертки более высокого уровня вокруг набора результатов GSON + Sql. На странице jsp могут использоваться методы SqlIterator (sqlquery) (.next(), getColumnCount(), getType (idx),.getString(idx),.getLong(idx)...) при написании http-ответа. Он перемещает исходный sql без промежуточного списка. Это не важно для небольших приложений, но приложения с большим объемом использования должны более внимательно относиться к схемам использования cpu + ram. Или даже лучше использовать помощник SqlToJson (httpresponse, sqlrs), тогда jsp или код сервлета минимальны.
Ответ 4
Вы можете использовать любую библиотеку JSON.
Ниже приведена реализация этого, верните список, с каждым элементом JSON Object:
/*
* 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;
}
Ответ 5
- Преобразование результатов в
List<Map<String, Object>>
(каждая карта содержит строку с именами столбцов в качестве ключей и содержимого столбца как значение, List - список таких строк) - Используйте библиотеку Gson или Jackson для скрытия этого объекта в JSON.
Ответ 6
Это довольно легко, если вы хотите использовать 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).
Ответ 7
Используйте jsonlib для Java. Перейдите по набору результатов и добавьте свойства, которые вы хотите, в качестве JSONObject
объектов из jsonlib.
Ответ 8
В моих приложениях (MySQL/java servlet/javascript в браузере) я использую строковую функцию с быстрыми методами stringbuilder и родовым rs.getObject(). Я думаю, что это самый элегантный способ выполнить эту работу:
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();
}
Ответ 9
Я нашел лучшее решение здесь.
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;
}