Scala преобразует java.sql.ResultSet в объект Json

#scala #apache-spark

#scala #apache-spark

Вопрос:

Я использую Spark 2.3.1, и я извлек результирующий набор из MySQL, используя соединение JDBC. ResultSet — это тип java.sql.ResultSet. итак, как преобразовать ResultSet в объект JSON.

Мне не нужно использовать Spark SQL

Код для извлечения результирующего набора таков

 var connection:Connection = null
connection: java.sql.Connection = null

scala> Class.forName(driver)
res0: Class[_] = class com.mysql.jdbc.Driver

scala> connection = DriverManager.getConnection(url, username, password)
connection: java.sql.Connection = com.mysql.jdbc.JDBC4Connection@79777da7

scala> val statement = connection.createStatement()
statement: java.sql.Statement = com.mysql.jdbc.StatementImpl@68360fb9

scala> val resultSet = statement.executeQuery("SELECT * FROM table_name")
resultSet: java.sql.ResultSet = com.mysql.jdbc.JDBC42ResultSet@4ebed2b3
  

Ответ №1:

вы можете получить мету результирующего набора и подсчитать количество столбцов, а затем выполнить итерацию:

 val meta = resultSet.getMetaData
val colsCount = meta.getColumnCount
var colsMap: Map[Int, String] = Map.empty[Int, String]
// save col index and colName to a map, to compute later json with "key" and value
for (i <- 1 to colsCount) {
   colsMap  =  i -> meta.getColumnName(i)
}

while (resultSet.next()) {
     for (i <- 1 to colsCount) {
        val value = resultSet.getObject(i)
        // here you take colName from specific index and save it in a list of JsValues
        // as { "colsMap(i)" : "value" }
        // using spray-json or any other json library
     }
}
  

Редактировать: Основываясь на моих исследованиях, я хочу расширить этот ответ.

Итак, чтобы преобразовать ResultSet в строку Json, я использую библиотеку JacksonMapper, для импорта этой библиотеки команда будет выглядеть следующим образом

 ./bin/spark-shell --packages "com.lambdaworks:jacks_2.11:2.3.3" --driver-class-path path-of/mysql-connector-java-5.1.49.jar 
--jars path-of/mysql-connector-java-5.1.49.jar 
-i path-to/ScalaApp.scala 
  

Фрагмент программы

 import scala.collection.mutable.ArrayBuffer

import scala.collection.mutable.Map
import com.lambdaworks.jacks._

val meta = query_resultSet.getMetaData
    
    // Get total column count from metadata
    val colsCount = meta.getColumnCount
    var colsMap: Map[Int, String] = Map.empty[Int, String]
    
    // Create ArrayBuffer[ArrayBuffer[Map(String, String)]]
    var final_array = ArrayBuffer[ArrayBuffer[scala.collection.mutable.Map[String, String]]]()
    
    // Fill colsMap from columnName
    for (i <- 1 to colsCount) {
        colsMap  =  i -> meta.getColumnName(i)
    }

    while (query_resultSet.next()) {
        var result_array = ArrayBuffer[scala.collection.mutable.Map[String, String]]()
        for (i <- 1 to colsCount)
        {
            var temp_map = scala.collection.mutable.Map[String, String]()
            val cols = colsMap(i)
            val value = query_resultSet.getObject(i)
            temp_map(s"$cols") = s"$value"
            result_array  = temp_map
        }
        final_array  = result_array
    }

    // for Array: use JacksMapper to convert ArrayBuffer[Map(String, String)] to [{"column1":"value1"},{"column2":"value2"}]
    
     val  json_string = JacksMapper.writeValueAsString(final_array)
  

Здесь мы используем библиотеку Jackson Mapper для преобразования значений карты в строку Json.

Ответ №2:

Вы можете сделать что-то вроде этого:

 import value.{JsObj,JsArray}
val emp = JsObjSpec("name" -> getNameFromRS()),
                           "last_name" -> str(getNameFromRS()),
                           "profession" -> str(getProfFromRS()), 
                           "country" -> enum("US"),               
                           "languages" -> arrayOfStr((getLangFromRS()),
                           "age" -> getAgeFromRS(),,
                           * -> any 
                           )
  

Комментарии:

1. На самом деле во время выполнения у меня нет знаний о схеме таблицы, потому что запрос будет выполняться к таблицам в соответствии с переменной цикла, поэтому не могли бы вы уточнить свой ответ, потому что я новичок в scala.

Ответ №3:

Если здесь можно использовать стороннюю библиотеку, вы можете использовать для этого функцию экспорта JSON jOOQ:

 DSLContext ctx = ...
String json = ctx.fetch(resultSet).formatJSON();
  

Существуют различные параметры форматирования JSON для разных макетов записей и результатов. Приведенный выше пример считывается непосредственно из вашего JDBC ResultSet , но вы могли бы, конечно, также создать и выполнить свой запрос с помощью jOOQ напрямую или использовать встроенную поддержку SQL / JSON. Часто нет необходимости писать какую-либо логику промежуточного программного обеспечения, когда вы хотите создать JSON из результатов базы данных. Вы могли бы сгенерировать JSON непосредственно из SQL.

Отказ от ответственности: я работаю в компании, стоящей за jOOQ.