2014-04-20 44 views
0

在Scala中,我怎样才能最直接地将MySql查询的结果发送给JSON字符串?我们在“play”框架内工作,并使用“光滑”连接到MySQL,所以我更具体地尝试将slick's StaticQuery SELECT的结果直接映射到play JsValue对象。然而,对于一般问题的任何解决方案都是受欢迎的如何发送Scala的结果StaticQuery SELECT查询直接发送到JSON对象

查询字符串的select参数是动态插入的,它们具有已知的MySQL类型,但我通常不知道编译时的具体参数或它们的数量。

我有一种感觉,有一种巧妙的方法来处理case case和Map对象,但我希望有人已经更简单地解决了这个问题。例如有这个相关的Java Gist

比如我现在有:

import play.api.libs.json._ 
import scala.slick.jdbc.{GetResult, StaticQuery => Q} 

... 

case class SrResult(id: Int, user_id: Int, title: String) 
implicit val getSrResult = GetResult(r => SrResult(r.<<, r.<<, r.<<)) 

val qSql = "SELECT id,user_id,title from MYTABLE LIMIT 10" 
val q = Q.queryNA[SrResult](qSql) 

我会动态插入“是,USER_ID,标题为”入QSQL字符串,这样Q.queryNA的返回类型“SrResult”是不是在请编译时未知。

为了完整这里是我的工作的示例表:

CREATE TABLE `MYTABLE` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `USER_ID` int(11) NOT NULL, 
    `TITLE` varchar(254) NOT NULL, 
    `DESCRIPTION` text 
    `ARCHIVED` tinyint(1) NOT NULL, 
    `CREATED_AT` bigint(20) NOT NULL, 
    `END_DATE` date NULL, 
    PRIMARY KEY (`ID`), 
    KEY `TEST_USER_INDEX` (`USER_ID`), 
    CONSTRAINT `TEST_USER_FK` FOREIGN KEY (`USER_ID`) REFERENCES `USERS` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB AUTO_INCREMENT=1058 DEFAULT CHARSET=utf8; 

回答

0

this Stackoverflow answer解释如何得到一个地图了油滑普通的SQL查询。您需要调整它以将其限制为仅限于您所需的字段。在Map中,使用您最喜欢的JSON库来获取JSON对象应该是微不足道的。

+0

谢谢您的回答。我的情况面临的挑战之一是我需要捕获值的隐式JSON类型,而不仅仅是它们的字符串表示。 – mjhm

0

我最终在解析ResultSet from an executeQueryPlay's Json tools的较低JDBC级别工作。例如:

import play.api.libs.json._ 
import utils.DatabaseConfig.driver.simple._ 
import slick.session.Database.threadLocalSession 
import java.sql.{Connection, DriverManager, ResultSet}; 
import java.util.Date 

... 

val rs = statement.executeQuery("SELECT * FROM USERS") 

jsValueResult = sqlResultSetToJson(rs) 

其中

def sqlResultSetToJson(rs: ResultSet): JsValue = { 
    // This is loosely ported from https://gist.github.com/kdonald/2137988 

    val rsmd = rs.getMetaData 
    val columnCount = rsmd.getColumnCount 

    // It may be faster to collect each line into a Seq or other iterable 
    // and pass that to Json.arr() at the end. 
    var qJsonArray: JsArray = Json.arr() 
    while (rs.next) { 
    var index = 1 

    var rsJson: JsObject = Json.obj() 
    while (index <= columnCount) { 
     // Unfortunately jdbc ResultSetMetaData doesn't expose a reliable 
     // getTableName method. It returns the "originalTableName" which doesn't 
     // include table aliases defined in the SELECT statement. 
     // Therefore the table name needs to be hard coded into each column 
     // name in the SELECT command. 
     // 
     // We should also be checking that there are no duplicate columnLabel's 
     // The Json constructors will just mindlessly append items with dup names 
     // to the JsObject. 
     val column = rsmd.getColumnLabel(index) 
     val columnLabel = column.toLowerCase() 

     val value = rs.getObject(column) 
     if (value == null) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> JsNull 
     ) 
     } else if (value.isInstanceOf[Integer]) { 
     println(value.asInstanceOf[Integer]) 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Int] 
     ) 
     } else if (value.isInstanceOf[String]) { 
     println(value.asInstanceOf[String]) 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[String] 
     ) 
     } else if (value.isInstanceOf[Boolean]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Boolean] 
     ) 
     } else if (value.isInstanceOf[Date]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Date].getTime 
     ) 
     } else if (value.isInstanceOf[Long]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Long] 
     ) 
     } else if (value.isInstanceOf[Double]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Double] 
     ) 
     } else if (value.isInstanceOf[Float]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[Float] 
     ) 
     } else if (value.isInstanceOf[BigDecimal]) { 
     rsJson = rsJson ++ Json.obj(
      columnLabel -> value.asInstanceOf[BigDecimal] 
     ) 
     // } else if (value.isInstanceOf[Byte]) { 
     // rsJson = rsJson ++ Json.obj(
     //  columnLabel -> value.asInstanceOf[Byte] 
     // ) 
     // } else if (value.isInstanceOf[Array[Byte]]) { 
     // rsJson = rsJson ++ Json.obj(
     //  columnLabel -> value.asInstanceOf[Array[Byte]] 
     // ) 
     } else { 
     throw new IllegalArgumentException("Unmappable object type: " + value.getClass) 
     } 
     index += 1 
    } 
    qJsonArray = qJsonArray :+ rsJson 
    } 
    qJsonArray 
}