枚举圆序列化

克里斯·约翰斯顿

我有一个简单的案例类,像这样:

case class ColumnMetadata(name: String,
                          displayName: String,
                          description: Option[String],
                          attributeType: AttributeType)

sealed trait AttributeType extends EnumEntry

case object AttributeType extends Enum[AttributeType] with CirceEnum[AttributeType] {

 val values: immutable.IndexedSeq[AttributeType] = findValues

  case object Number extends AttributeType
  case object Text extends AttributeType
  case object Percentage extends AttributeType
}

和半自动编码器:

package object circe {

  implicit val config: Configuration = Configuration.default.withSnakeCaseMemberNames


  implicit val columnMetaDecoder: Decoder[ColumnMetadata] = deriveConfiguredDecoder
  implicit val columnMetaEncoder: Encoder[ColumnMetadata] = deriveConfiguredEncoder

  implicit val columnTypeDecoder: Decoder[AttributeType] = deriveConfiguredDecoder
  implicit val columnTypeEncoder: Encoder[AttributeType] = deriveConfiguredEncoder
}

但是,当我进行序列化测试时:

  ColumnMetadata("column1", "Column 1", Some("column1"), 
    AttributeType.withName("Text")).asJson

我得到:

  {
    "name" : "column1",
    "display_name" : "Column 1",
    "description" : "column1",
    "attribute_type" : {
      "Text": {}
    }
  }

当我想要的时候:

  {
    "name" : "column1",
    "display_name" : "Column 1",
    "description" : "column1",
    "attribute_type" : "Text"
  } 

当我使用自动派生但我想使用半自动派生时,它可以工作,因此我可以使用诸如withSnakeCaseMemberNames之类的功能。

马特乌斯·库布佐克(Mateusz Kubuszok)

这是您的错误:


  implicit val columnTypeDecoder: Decoder[AttributeType] = deriveConfiguredDecoder
  implicit val columnTypeEncoder: Encoder[AttributeType] = deriveConfiguredEncoder

这将派生新的编解码器,将其AttributeType视为任何其他密封特性,因此它将使用判别值(半自动始终忽略它们派生的类型的现有编解码器!)。

因此,您要派生一个新的AttributeType编解码器,将它们放在使用它们的范围内,从而使这些新的实现比同伴对象的实现具有更高的优先级。隐性接近总是赢。

如果您不导出编解码器(因为CirceEnumtrait已经提供了现有的实现),那么它将按预期工作。

另外,不要这样做:

  implicit val columnMetaDecoder: Decoder[ColumnMetadata] = deriveConfiguredDecoder
  implicit val columnMetaEncoder: Encoder[ColumnMetadata] = deriveConfiguredEncoder

您可以这样做:

// make sure that Configuration is in scope by e.g. importing it
// or putting it in package object in the same package as case class
@ConfiguredJsonCodec
case class ColumnMetadata(name: String,
                          displayName: String,
                          description: Option[String],
                          attributeType: AttributeType)

这将使您省去创建编解码器包并手动将其导入到任何需要它们的地方。例如

// imports

package object models_package {

  private[models_package] implicit val config: Configuration = Configuration.default.withSnakeCaseMemberNames
}
package models_package

// imports

@ConfiguredJsonCodec
case class ColumnMetadata(name: String,
                          displayName: String,
                          description: Option[String],
                          attributeType: AttributeType)

sealed trait AttributeType extends EnumEntry
object AttributeType extends Enum[AttributeType] with CirceEnum[AttributeType] {

 val values: immutable.IndexedSeq[AttributeType] = findValues

  case object Number extends AttributeType
  case object Text extends AttributeType
  case object Percentage extends AttributeType
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章