抽象类上的 Json.reads(不支持密封特征:没有已知的子类)
Posted
技术标签:
【中文标题】抽象类上的 Json.reads(不支持密封特征:没有已知的子类)【英文标题】:Json.reads on abstract class (Sealed trait is not supported: no known subclasses) 【发布时间】:2021-10-21 11:44:16 【问题描述】:我有一个抽象类和对象
sealed abstract class Granularity()
// some values and methods
object Granularity
final private case class WeekGranularity(name: String, windowSize: Int) extends Granularity("week", "'7' day")
// overriding methods
val Week: Granularity = WeekGranularity(name = "week", windowSize = 1)
我在其他类似的课程中使用它
case class Meta(granularity: Granularity)
object Meta
implicit val granularityWrites = Writes[Granularity](d => JsString(d.toString))
implicit val metaWrites = Json.writes[Meta]
现在在编写这样的规范时,我得到一个错误
class ControllerSpec
"MetaController" should
"return"
.
.
.
// play 2.13 resp
resp.body[JsValue].asOpt[Meta] should beSome(expectedMeta)
// ERROR: No Json deserializer found for type models.Meta. Try to implement an implicit Reads or Format for this type
当我在 Spec 类的顶部添加一个隐式读取时,我仍然得到一个错误
implicit val granularityReads = Json.reads[Granularity] // ERROR: Sealed trait Granularity is not supported: no known subclasses
implicit val metaReads = Json.reads[Meta]
我可以这样做来比较 json,它可以工作而且我不必创建任何隐式。
resp.body[JsValue] shouldEqual Json.toJson(metricSignTimeseries)
但我想了解如何实现隐式读取粒度?
【问题讨论】:
你有理由不为WeekGranularity
定义Reads
吗?
【参考方案1】:
为了从 JSON 数据中读取 Granularity
,库必须能够创建 Granularity
的实例才能返回它。但是Granularity
是abstract class
,你不能创建抽象类的实例。
Json.reads
需要使用可由库实例化的具体类进行参数化,或者您需要编写自定义 Reads[Granularity]
来创建并返回 Granularity
的适当子类。
我建议您不要将功能放在用于读取/写入 JSON 或使用复杂类层次结构的类中。只需将数据读入直接匹配JSON格式的简单case class
实例,然后处理成应用类即可。这允许存储格式和内部应用程序数据格式独立更改,而不是紧密联系。
【讨论】:
以上是关于抽象类上的 Json.reads(不支持密封特征:没有已知的子类)的主要内容,如果未能解决你的问题,请参考以下文章