从Scala中的JSON解析/提取信息

时间:2017-06-12 10:31:30

标签: json scala pattern-matching

我试图从第三方JSON消息中提取(时间戳,值)元组:

{
    "data": {
        "1496845320000": [
            0.14
        ],
        "1496845380000": [
            0.14
        ],
        "1496845560000": [
            0.14
        ],
        "1497013740000": [
            "undef"
        ],
        "1497013800000": [
            "undef"
        ],
        "1497013860000": [
            "undef"
        ]
    },
    "status": "ok"
}

这就是我提取JSON实体的方式:

val batchReadings = http.singleRequest(httpRequest) map {
  case HttpResponse(StatusCodes.OK, headers, entity, _) =>
    entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
      JSON.parseFull(body.utf8String) match {
        case Some(e: Map[String, Any]) =>
          e.get("status") match {
            case Some("ok") => println("ok!")
              e.get("data") match {
                case Some(f: Map[String, List[Any]]) =>
                  println("entered second case")
                  new EfergyReadingsData(f.toList).getReadings
              }
            case _ => log.info("EfergyReaderWorkerActor: Received unknown message\n" + body.utf8String)
          }
      }

    }
  case HttpResponse(code, _, entity, _) =>
    //entity.toStrict(100, materializer)   N.B. Not having this, will freeze after 4 calls!
    s"Response code: $code"
  case unknown =>
    s"unknown response: $unknown"
}

这是EfergyReadingsData类:

class EfergyReadingsData(readings: List[(String, List[Any])]) {
  def getReadings: List[(Long, Double)] = {
    println(readings)
    //    List((1123, 34.4))
    val filteredReadings = readings filter {
      f =>
      f._2 match {
        case  t:List[Any] =>
          t.head match {
            case Double => true
            case _ => false
          }
      }
    }
    val theRead = filteredReadings map {
      p => (p._1.toLong, p._2.head)
    }
    println(theRead)
    List((1123, 34.4))
  }
}

正如您所看到的那样,我没有返回我在getReadings中应该使用的元组列表,我只是创建了一个要返回的列表,以便我可以测试代码。

除了无法过滤列表以仅删除undef条目(filteredReadings为空)之外,这种方法的第一个明显问题是我对类型的模式匹配在List和Map中,因此得到一个关于那些未被检查的警告,因为它们被擦除消除了。

虽然为简单起见没有在上面表示,但我试图通过使用列表的案例类来缓解这个问题:

sealed abstract class AnyReading {
  val value: List[Any]
}

case class SuccessfulReading(override val value: List[Double]) extends AnyReading

case class FailedReading(override val value: List[String]) extends AnyReading

因此,总结一下,最好的方法是什么?我还考虑创建几个案例类来表示JSON结构,并尝试反序列化JSON消息,然后过滤以删除undef值,最终得到我想要的元组列表。

提前感谢您的帮助。

0 个答案:

没有答案