akka http有一个json模块专门用于处理json和scala类型之间的转换,通常接口以json格式作为结果响应格式,如果使用此功能,在项目的配置中引入json包,gradle引入如下:
compile 'com.typesafe.akka:akka-http-spray-json_2.12:10.1.3'
如果是maven构建项目,则是:
com.typesafe.akka
akka-http-spray-json_2.12
10.1.4
json和Map类型之间可以很好的转换,其他类型也可以:
需要注意的是,对于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":{}}
响应结果如下: