首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Circe Encoding Sealed and Co Product Case类失败

Circe Encoding Sealed and Co Product Case类失败
EN

Stack Overflow用户
提问于 2020-11-26 02:24:43
回答 1查看 186关注 0票数 0

我有以下case类:

代码语言:javascript
复制
case class SmartMeterData(
  dateInterval: SmartMeterDataInterval = HalfHourInterval(),
  powerUnit: PowerUnit = KWH,
  smartMeterId: String,
  timestamp: String,
  value: Double
) {
  def timeIntervalInDuration: FiniteDuration = dateInterval match {
    case HalfHourInterval(_) => FiniteDuration(30, TimeUnit.MINUTES)
    case FullHourInterval(_) => FiniteDuration(60, TimeUnit.MINUTES)
  }
}
object SmartMeterData {
  sealed trait SmartMeterDataInterval { def interval: String }
  case class HalfHourInterval(interval: String = "HH") extends SmartMeterDataInterval
  case class FullHourInterval(interval: String = "FH") extends SmartMeterDataInterval

  sealed trait PowerUnit
  case object WH  extends PowerUnit
  case object KWH extends PowerUnit
  case object MWH extends PowerUnit
}

我只是写了一个非常简单的单元测试,看看Circe是否适用于我的场景:

代码语言:javascript
复制
"SmartMeterData" should "successfully parse from a valid JSON AST" in {
    val js: String = """
      {
        "dateInterval" : "HH",
        "powerUnit" : "KWH",
        "smartMeterId" : "LCID-001-X-54",
        "timestamp" : "2012-10-12 00:30:00.0000000",
        "value" : 23.0
      }
      """
    val expectedSmartMeterData = SmartMeterData(smartMeterId = "LCID-001-X-54", timestamp = "2012-10-12 00:30:00.0000000", value = 23.0)
    decode[SmartMeterData](js) match {
      case Left(err) => fail(s"Error when parsing valid JSON ${err.toString}")
      case Right(actualSmartMeterData) =>
        assert(actualSmartMeterData equals expectedSmartMeterData)
    }
  }

但它失败了,并显示以下错误:

代码语言:javascript
复制
Error when parsing valid JSON DecodingFailure(CNil, List(DownField(dateInterval)))

circe有没有一个已知的限制,它还不适用于我上面的情况?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-26 07:49:14

Circe没有理由不工作,但是按照您设计数据模型的方式,基本上不可能有任何Scala JSON库能够自动生成编码器/解码器,而无需大量的手动工作。

例如

代码语言:javascript
复制
sealed trait SmartMeterDataInterval { def interval: String }
case class HalfHourInterval(interval: String = "HH") extends SmartMeterDataInterval
case class FullHourInterval(interval: String = "FH") extends SmartMeterDataInterval

在自动派生case classes实例的任何Scala JSON库中,这两者的模式都是这样的

代码语言:javascript
复制
{ "interval": "HH" }

对于HalfHourInterval

代码语言:javascript
复制
 { "interval": "FH" }

对于FullHourInterval (即,因为它们都有一个名为interval的字符串字段,所以它们实际上是同一个类)。事实上,你的模型允许你使用FullHourInterval("HH"),对于至少一种为circe中的ADT层次结构生成解码器的方法(文档中使用shapeless的方法)来说,这将是解码{ "interval": "HH" }的结果,因为这本质上是以词法顺序匹配的第一个构造函数(即FullHourInterval)。如果其目的是只允许完整或半小时的间隔,那么我建议将其表达为:

代码语言:javascript
复制
case object HalfHourInterval extends SmartMeterDataInterval { def interval: String = "HH" } 
case object FullHourInterval extends SmartMeterDataInterval { def interval: String = "FH" }

我并不直接熟悉case object是如何编码SmartMeterDataInterval的,但是您可以很容易地为circe定义一个编码器和解码器

代码语言:javascript
复制
object SmartMeterDataInterval {
  implicit val encoder: Encoder[SmartMeterDataInterval] =
    Encoder.encodeString.contramap[SmartMeterDataInterval](_.interval)
  implicit val decoder: Decoder[SmartMeterDataInterval] =
    Decoder.decodeString.emap {
      case "HH" => Right(HalfHourInterval)
      case "FH" => Right(FullHourInterval)
      case _ => Left("not a valid SmartMeterDataInterval")
    }
 }

然后,您将执行类似于为PowerUnit定义Encoder/Decoder的操作

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65010652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档