MySQL ResultSet进入Gson数组

时间:2017-03-06 22:15:04

标签: json java-8 gson

我想使用Gsons库将MySQL结果集放入JsonArray中。我怎样才能做到最好。我读过这个: resultset to json using gson

但它出于某种原因使用了简单的Json库。如果可能,我不希望这样。有没有办法用gson库轻松实现这个目标?

非常感谢!

PlayerList.java:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.freakyonline.ucone;

import de.freakyonline.ucone.Player;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TextArea;

/**
 *
 * @author uwe
 */
public class PlayerList {

    ObservableList<Player> playerList;
    ObjectInputStream in;
    ObjectOutputStream out;
    Socket sock;
    private Object obj = null;
    private Object obj2 = null;
    TextArea consoleOneTextArea;

    public PlayerList(ObjectInputStream in, ObjectOutputStream out, Socket sock, TextArea consoleOneTextArea) {
        this.in = in;
        this.out = out;
        this.sock = sock;
        this.consoleOneTextArea = consoleOneTextArea;
        getPlayersFromServer();
    }

    private void getPlayersFromServer() {

/*        try {
            out.writeObject("getplayers");
            obj=in.readObject();

            if(obj == null) { 
                System.out.println("ERROR! void getPlayersFromServer in PlayerList.java");
                Platform.exit(); 
            }

            String command = obj.toString().toLowerCase();
            String currentFromServer;

            if(command.equalsIgnoreCase("getplayers")) { 
                while((obj2=in.readObject()) != null) {
                    currentFromServer = obj2.toString().toLowerCase();

                    for(String cell : currentFromServer.split(" ")) {
                        System.out.println(cell.toString());                           
                    }


                    if (currentFromServer.equalsIgnoreCase("done")) {
                        consoleOneTextArea.appendText("This is finished. Have fun!\n");
                        break;
                    }

                    consoleOneTextArea.appendText(currentFromServer + "\n");
                }

            } { System.out.println("ERROR"); }
        } catch (Exception ex) { ex.printStackTrace(); }
*/

        this.playerList = FXCollections.observableArrayList(
        new Player("freakyy85","Owner","1810",31,"m", "missing..."),
        new Player("Ky3ak","Owner","1920",34,"m", "missing...")
        );
    }
}

(香港专业教育学院评论了一些部分,因为它们不再相关)

Player.java:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.freakyonline.ucone;

import com.google.gson.stream.JsonReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import javafx.scene.control.TextArea;

/**
 *
 * @author uwe
 */
public class Remote implements Runnable {
    private Object obj = null;
    private Object obj2 = null;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private Socket sock;

    private TextArea consoleOneTextArea;

    public Remote (ObjectInputStream in, ObjectOutputStream out, Socket sock) {
        this.in = in;
        this.out = out;
        this.sock = sock;
    }

    public ObjectInputStream getIn() {
        return in;
    }

    public ObjectOutputStream getOut() {
        return out;
    }

    public Socket getSock() {
        return sock;
    }

    public void setConsoleOneTextArea(TextArea consoleOneTextArea) {
        this.consoleOneTextArea = consoleOneTextArea;
    }

    public void run() {
        try {
            while((obj=in.readObject()) != null && sock.isConnected()) {
                String command = obj.toString().toLowerCase();
                String currentFromServer;

                switch(command) {
                    case "getplayers": 
/*                      while((obj2=in.readObject()) != null) {
                            currentFromServer = obj2.toString().toLowerCase();

                            if (currentFromServer.equalsIgnoreCase("done")) {
                                consoleOneTextArea.appendText("This is finished. Have fun!\n");
                                break;
                            }

                            consoleOneTextArea.appendText(currentFromServer + "\n");
*/                        }

                        JsonReader jsonReader = new JsonReader(new InputStreamReader(in, "UTF-8"));




                        jsonReader.close();

                        break;
                }
        } catch (Exception ex) { ex.printStackTrace(); }
    }

}

1 个答案:

答案 0 :(得分:2)

  

使用gson库有没有办法轻松实现这个目标?

不是真的。 Gson和JDBC是两个不相关的东西,所以你必须实现一个自定义重映射功能来解码&#34; JDBC结果集行/字段和&#34;编码&#34;它们分别返回JSON数组/对象。从内存消耗的角度来看,累积JsonArray实例可能会很昂贵,甚至会使应用程序崩溃OutOfMemoryError以获得巨大的结果集。尽管如此,如果已知结果集较小或LIMIT,则它们很好。

累积JsonArray

static JsonArray resultSetToJsonArray(final ResultSet resultSet)
        throws SQLException {
    final ResultSetMetaData metaData = resultSet.getMetaData();
    // JsonArray is a Gson built-in class to hold JSON arrays
    final JsonArray jsonArray = new JsonArray();
    while ( resultSet.next() ) {
        jsonArray.add(resultSetRowToJsonObject(resultSet, metaData));
    }
    return jsonArray;
}

private static JsonElement resultSetRowToJsonObject(final ResultSet resultSet, final ResultSetMetaData metaData)
        throws SQLException {
    final int columnCount = metaData.getColumnCount();
    // Every result set row is a JsonObject equivalent
    final JsonObject jsonObject = new JsonObject();
    // JDBC uses 1-based loops
    for ( int i = 1; i <= columnCount; i++ ) {
        jsonObject.add(metaData.getColumnName(i), fieldToJsonElement(resultSet, metaData, i));
    }
    return jsonObject;
}

private static JsonElement fieldToJsonElement(final ResultSet resultSet, final ResultSetMetaData metaData, final int column)
        throws SQLException {
    final int columnType = metaData.getColumnType(column);
    final Optional<JsonElement> jsonElement;
    // Process each SQL type mapping a value to a JSON tree equivalent
    switch ( columnType ) {
    case Types.BIT:
    case Types.TINYINT:
    case Types.SMALLINT:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    case Types.INTEGER:
        // resultSet.getInt() returns 0 in case of null, so it must be extracted with getObject and cast, then converted to a JsonPrimitive
        jsonElement = Optional.ofNullable((Integer) resultSet.getObject(column)).map(JsonPrimitive::new);
        break;
    case Types.BIGINT:
    case Types.FLOAT:
    case Types.REAL:
    case Types.DOUBLE:
    case Types.NUMERIC:
    case Types.DECIMAL:
    case Types.CHAR:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    case Types.VARCHAR:
        jsonElement = Optional.ofNullable(resultSet.getString(column)).map(JsonPrimitive::new);
        break;
    case Types.LONGVARCHAR:
    case Types.DATE:
    case Types.TIME:
    case Types.TIMESTAMP:
    case Types.BINARY:
    case Types.VARBINARY:
    case Types.LONGVARBINARY:
    case Types.NULL:
    case Types.OTHER:
    case Types.JAVA_OBJECT:
    case Types.DISTINCT:
    case Types.STRUCT:
    case Types.ARRAY:
    case Types.BLOB:
    case Types.CLOB:
    case Types.REF:
    case Types.DATALINK:
    case Types.BOOLEAN:
    case Types.ROWID:
    case Types.NCHAR:
    case Types.NVARCHAR:
    case Types.LONGNVARCHAR:
    case Types.NCLOB:
    case Types.SQLXML:
    case Types.REF_CURSOR:
    case Types.TIME_WITH_TIMEZONE:
    case Types.TIMESTAMP_WITH_TIMEZONE:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    default:
        throw new UnsupportedOperationException("Unknown type: " + columnType);
    }
    // If the optional value is missing, assume it's a null
    return jsonElement.orElse(JsonNull.INSTANCE);
}
final JsonArray jsonArray = resultSetToJsonArray(resultSet);
System.out.println(jsonArray);

当然,别忘了关闭resultSet

JSON流媒体

如果JsonArray应该写在别处,JsonWriter可以是一个更好的解决方案,能够处理逐行读取的大型结果集,并通过JSON元素编写JSON元素。

@SuppressWarnings("resource")
static void resultSetToJsonArrayStream(final ResultSet resultSet, final JsonWriter jsonWriter)
        throws SQLException, IOException {
    // Write the [ token
    jsonWriter.beginArray();
    final ResultSetMetaData metaData = resultSet.getMetaData();
    while ( resultSet.next() ) {
        // Write row by row
        writeRow(resultSet, jsonWriter, metaData);
    }
    // Finish the array with the ] token
    jsonWriter.endArray();
}

@SuppressWarnings("resource")
private static void writeRow(final ResultSet resultSet, final JsonWriter jsonWriter, final ResultSetMetaData metaData)
        throws SQLException, IOException {
    final int columnCount = metaData.getColumnCount();
    // Similarly to the outer array: the { token starts a new object representing a row
    jsonWriter.beginObject();
    for ( int i = 1; i <= columnCount; i++ ) {
        // Write the column name and try to resolve a JSON literal to be written
        jsonWriter.name(metaData.getColumnName(i));
        writeField(resultSet, jsonWriter, metaData, i);
    }
    // Terminate the object with }
    jsonWriter.endObject();
}

@SuppressWarnings("resource")
private static void writeField(final ResultSet resultSet, final JsonWriter jsonWriter, final ResultSetMetaData metaData, final int column)
        throws SQLException, IOException {
    final int columnType = metaData.getColumnType(column);
    switch ( columnType ) {
    case Types.BIT:
    case Types.TINYINT:
    case Types.SMALLINT:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    case Types.INTEGER:
        jsonWriter.value((Integer) resultSet.getObject(column));
        break;
    case Types.BIGINT:
    case Types.FLOAT:
    case Types.REAL:
    case Types.DOUBLE:
    case Types.NUMERIC:
    case Types.DECIMAL:
    case Types.CHAR:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    case Types.VARCHAR:
        jsonWriter.value((String) resultSet.getObject(column));
        break;
    case Types.LONGVARCHAR:
    case Types.DATE:
    case Types.TIME:
    case Types.TIMESTAMP:
    case Types.BINARY:
    case Types.VARBINARY:
    case Types.LONGVARBINARY:
    case Types.NULL:
    case Types.OTHER:
    case Types.JAVA_OBJECT:
    case Types.DISTINCT:
    case Types.STRUCT:
    case Types.ARRAY:
    case Types.BLOB:
    case Types.CLOB:
    case Types.REF:
    case Types.DATALINK:
    case Types.BOOLEAN:
    case Types.ROWID:
    case Types.NCHAR:
    case Types.NVARCHAR:
    case Types.LONGNVARCHAR:
    case Types.NCLOB:
    case Types.SQLXML:
    case Types.REF_CURSOR:
    case Types.TIME_WITH_TIMEZONE:
    case Types.TIMESTAMP_WITH_TIMEZONE:
        throw new UnsupportedOperationException("TODO: " + JDBCType.valueOf(columnType));
    default:
        throw new UnsupportedOperationException("Unknown type: " + columnType);
    }
}

写入System.out的示例,但是,当然,只要提供适当的OutputStream实例,就可以将其写入:

final JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(System.out))
resultSetToJsonArrayStream(resultSet, jsonWriter);

ResultSet类似,JsonWriter也必须关闭。

我已经为SQLite编写了上面的代码,但它也适用于MySQL。例如,使用以下SQL语句创建和填充测试数据库:

CREATE TABLE `table` (i NUMBER NOT NULL, s TEXT NOT NULL);
INSERT INTO `table` (i, s) VALUES (1, 'foo');
INSERT INTO `table` (i, s) VALUES (2, 'bar');
INSERT INTO `table` (i, s) VALUES (3, 'baz');

将导致

  

[{&#34; I&#34;:1,&#34; S&#34;:&#34;富&#34;},{&#34; I&#34;:2&#34 ; S&#34;:&#34; BAR&#34;},{&#34; I&#34;:3,&#34; S&#34;:&#34;巴兹&#34;}]

对象模型和流媒体方法。