AKKA HTTP查詢結果返回JSON字串
阿新 • • 發佈:2018-11-07
akka http有一個json模組專門用於處理json和scala型別之間的轉換,通常介面以json格式作為結果響應格式,如果使用此功能,在專案的配置中引入json包,gradle引入如下:
compile 'com.typesafe.akka:akka-http-spray-json_2.12:10.1.3'
如果是maven構建專案,則是:
<dependency> <groupId>com.typesafe.akka</groupId> <artifactId>akka-http-spray-json_2.12</artifactId> <version>10.1.4</version> </dependency>
json和Map型別之間可以很好的轉換,其他型別也可以:
- Byte, Short, Int, Long, Float, Double, Char, Unit, Boolean
- String, Symbol
- BigInt, BigDecimal
- Option, Either, Tuple1 - Tuple7
- List, Array
- immutable.{Map, Iterable, Seq, IndexedSeq, LinearSeq, Set, Vector}
- collection.{Iterable, Seq, IndexedSeq, LinearSeq, Set}
- JsValue
需要注意的是,對於Map型別,如上標紅所示,只是針對immutable型別而言。如果你需要對mutable的Map做json響應轉換,可以先將其轉為immutable Map(map.toMap即可)即可。
如何將scala型別的Map轉為json字串?
1.定義響應的資料模型
首先明確需要響應的資料模型是什麼,比如如果是key,value型別的資料,則Map物件即可,如果是複雜的可進行巢狀,如:
final case class Items(items:Map[String, List[Map[String,String]]])//一個複雜的響應結果資料模型,注意均是不可變的型別
2.定義json隱式變數
implicit val itemsFormat = jsonFormat1(Items)//定義json格式化隱式變數
3.返回資料模型物件
在業務邏輯處理完後,返回定義的資料模型物件後,使用
complete(item.items)
即可返回json字串,從響應的報文中可看出:Content-Type: application/json,已將響應頭自動設定為json格式。
具體核心程式碼如下:
route部分:
final case class SensorsModel(keys:Map[String,String],conditions:Map[String,String])
implicit val sensorsModelFormat = jsonFormat2(SensorsModel)
val route = post {
path("user") {
entity(as[SensorsModel]) { model =>//這裡的SensorsModel類是自定義的請求引數接受模型,如上,可按實際情況自定義
val startkey = model.keys.get("startkey") match {
case Some(item) => item
case _ => ""
}
val endkey = model.keys.get("endkey") match {
case Some(item) => item
case _ => ""
}
val result: Future[Option[Items]] = selectByRangeKey(startkey,endkey,model.conditions)
onSuccess(result) {
case Some(item) => complete(item.items)
case None => complete(StatusCodes.NotFound)
}
}
}
}
查詢hbase邏輯程式碼部分:
def selectByRangeKey(startkey: String, endkey: String, conds:Map[String, String]): Future[Option[Items]] = {
val conn = HBaseConnection.getHBaseConn()
val tbl = conn.getTable(TableName.valueOf("xxxxx"))
val scan = new Scan()
scan.setStartRow(Bytes.toBytes(startkey))
scan.setStopRow(Bytes.toBytes(endkey))
scan.setCaching(10000)
val filterList = new FilterList()
if(conds.size>0){
for ((k, v) <- conds) {
filterList.addFilter(new SingleColumnValueFilter(Bytes.toBytes("data"), Bytes.toBytes(k), CompareOp.EQUAL, Bytes
.toBytes(v)))
}
scan.setFilter(filterList)
}
val rs = tbl.getScanner(scan).iterator()
var items:mutable.Map[String, List[Map[String,String]]] = new mutable.HashMap[String, List[Map[String,String]]]
var list = new ListBuffer[Map[String,String]]()
try {
while (rs.hasNext) {
var map = new mutable.HashMap[String,String]()
val cells = rs.next()
for (cell: Cell <- cells.rawCells()) {
val qf = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())
val value = Bytes.toString(cell.getValueArray, cell.getValueOffset, cell.getValueLength)
map.put(qf,value)
println("qf:"+qf+",value:"+value)
}
list+=map.toMap
}
items.put("result",list.toList)
} finally {
tbl.close()
conn.close()
}
val resultOption: Option[Items] = Some(new Items(items.toMap))
logInfo("Query Result:" + Some(items))
Future {
resultOption
}
}
還可以在程式碼中拼接json字串,結果響應時可指定響應內容為json:
complete(HttpEntity(ContentTypes.`application/json`,jsonResultString))
測試結果:
Text中的請求內容是:{"keys":{"startkey": "1001 ","endkey": "1003 "},"conditions":{}}
響應結果如下: