JDBC コネクタを使用した MySQL クエリの結果として結果セットがあります。したがって、私の仕事は結果セットを JSON 形式に変換することです。AJAX 応答としてクライアント側に送信できるようにします。私はJavaとJSONの概念の両方に慣れていないので、JSON形式への変換を行う方法を説明できますか
10 に答える
多くの人がその質問に正しく答えました。しかし、次の小さなコード スニペットを使用して、投稿にさらに価値を加えることができると思います。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);
}
JSON を使用している場合は、Jackson JSON ライブラリをお勧めします。
http://wiki.fasterxml.com/JacksonHome
jar ファイルは次の場所にあります。
http://wiki.fasterxml.com/JacksonDownload
結果セットを Map<> または List< Map<> に変換するために使用する一般的なコードを次に示します。これを 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;
}
サーブレットでは、Java Generics を JSON 文字列に変換する com.fasterxml.jackson.databind.ObjectMapper を使用して、List を 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 = ?";
}
mywebapp/WEB-INF/lib フォルダーにある 1 つの小さな gson-2.2.4.jar 190KB ライブラリである Google GSON ライブラリを使用しました。 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,etc..) セッターがあります。foreach rsmd ループ内で大文字と小文字の切り替えを行い、番号付きの sql 型に適切なセッターを使用します。デフォルトでは writer.value(rs.getString(idx)) セッターを使用できます。
JsonWriter を使用すると、大量の json 応答を CPU+RAM に効率的に書き込むことができます。最初に sqlresultset をループして、RAM に大量のリストを作成する必要はありません。次に、json ドキュメントの書き込み中にリストを再度ループします。この例では、HTTP 応答がチャンク化され、残りのデータがまだサーブレット出力に書き込まれています。
GSON+Sql 結果セットの周りに高レベルのラッパー ユーティリティを作成するのは比較的簡単です。jsp ページは、http 応答の書き込み中に SqlIterator(sqlquery) メソッド (.next()、getColumnCount()、getType(idx)、.getString(idx)、.getLong(idx) ...) を使用できます。中間リストなしで元のSQLをループします。これは小規模なアプリでは問題になりませんが、使用頻度の高いアプリでは、CPU + RAM の使用パターンをより綿密に考慮する必要があります。または、SqlToJson(httpresponse, sqlrs) ヘルパーを実行すると、jsp またはサーブレット コードのノイズが最小限に抑えられます。
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>
Jackson はクラスパスにある必要があります (つまり、Maven の依存関係)。
- 結果セットを次のように変換し
List<Map<String, Object>>
ます (各マップには、列名をキーとし、列の内容を値とする行が含まれます。List はそのような行のリストです) - Gson または Jackson ライブラリを使用して、このオブジェクトを JSON に変換します。
私のアプリケーション (ブラウザ上の MySQL/Java サーブレット/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();
}