AKKA HTTP查询结果返回JSON字符串

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类型之间可以很好的转换,其他类型也可以:

  • 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格式。

AKKA HTTP查询结果返回JSON字符串_第1张图片

具体核心代码如下:

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))

测试结果:

AKKA HTTP查询结果返回JSON字符串_第2张图片

Text中的请求内容是:{"keys":{"startkey": "1001 ","endkey": "1003 "},"conditions":{}} 

响应结果如下:

你可能感兴趣的:(AKKA HTTP查询结果返回JSON字符串)