【问题标题】:How to correctly do Pattern matching by type in this case?在这种情况下如何正确地按类型进行模式匹配?
【发布时间】:2017-11-14 22:04:59
【问题描述】:

我有一个用例,我想将鞍帧序列化为 Scala-Play Json。我让它适用于简单的元素类型,例如双倍,即Frame[DateTime, String, Double],但现在尝试序列化其元素是复杂类型的帧类型变得有点麻烦,例如Seq[(DateTime, Double)]

所以我有适用于原始元素类型的基本 frameWrites 实现:

import play.api.libs.json._
import org.saddle._
import org.joda.time._

object JsonUtils {
implicit def frameWrites[RX, CX, E] = new Writes[Frame[RX, CX, E]] {
  override def writes(frame: Frame[RX, CX, E]): JsValue = {
    val json: JsArray = Json.arr(
      (0 until frame.numRows).map { i =>
        Json.obj(
          frame.rowIx.at(i).toString ->
            (0 until frame.numCols).map { j =>
              Json.obj(
                frame.colIx.at(j).toString -> cellWrites(frame.at(i, j))
              )
            }
        )
      })
    json
  }
}}

所以我创建了一个cellWrites 来处理像这样的复杂元素类型:

object JsonUtils {
implicit def cellWrites[E](elem: E)(implicit tag: ClassTag[E]): JsValue = {
  elem match {
    case seq: Seq[(DateTime, Double)] => { 
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this should but doesn't happen
      Json.arr(
        seq.map { case (dt: DateTime, value: Double) =>
          Json.obj(dt.toString -> JsNumber(value))
        }
      )
    }
    case doubleValue: Double => JsNumber(doubleValue)
    case _ => JsString(elem.toString)
  }
}}

问题是我的 Frame 或类型 Frame[String, String, Seq[(DateTime, Double)]] 永远不会匹配 cellWrites 中适当的第一个案例。我还尝试使用隐式标记类型信息,但找不到将其用于模式匹配的方法。这是我使用的测试用例示例框架:

val today = DateTime.parse("2017-11-14T13:00:00.000+01:00")
val colIx = Index("x", "y")
val data = Seq(
  Series(
    "a" -> Seq(
        today.minusHours(2) -> 2.0,
        today.minusHours(1) -> 1.0,
        today.minusHours(0) -> 0.0
    ),
    "b" -> Seq(
      today.minusHours(1) -> 1.0,
      today.minusHours(0) -> 0.0
    )
  ),
  Series(
    "a" -> Seq(
      today.minusHours(5) -> 5.0,
      today.minusHours(4) -> 4.0,
      today.minusHours(3) -> 3.0
    ),
    "b" -> Seq(
      today.minusHours(4) -> 4.0,
      today.minusHours(3) -> 3.0
    )
  )
)
val frame: Frame[String, String, Seq[(DateTime, Double)]] = Frame(data, colIx)
println(frame)

请注意,上面的所有代码都可以正常编译。但是,单元格元素类型的模式匹配不起作用。

【问题讨论】:

    标签: json scala playframework saddle


    【解决方案1】:

    好的,找到了它,elem 实际上是 org.saddle.scalar.Scalar[E] 类型,因此这是可行的:

    implicit def cellWrites[E](scalar: Scalar[E]): JsValue = {
      val elem = scalar.get
      elem match {
        case seq: Seq[(DateTime, Double)] => {
          Json.arr(
            seq.map { case (dt: DateTime, value: Double) =>
              Json.obj(dt.toString -> JsNumber(value))
            }
          )
        }
        case doubleValue: Double => JsNumber(doubleValue)
        case _ => JsString(elem.toString)
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多