枚举循环序列化
Enumeratum Circe Serialisation
我有一个简单的案例 class 像这样:
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 之类的功能。
这是你的错误:
implicit val columnTypeDecoder: Decoder[AttributeType] = deriveConfiguredDecoder
implicit val columnTypeEncoder: Encoder[AttributeType] = deriveConfiguredEncoder
这将导出新的编解码器,将 AttributeType
视为任何其他密封特征,因此它将使用区分值(半自动总是忽略它们正在导出的类型的现有编解码器!)。
所以你正在派生一个新的 AttributeType
编解码器,将它们放在使用它们的范围内,因此使这些新实现比来自伴随对象的实现具有更高的优先级。越接近隐含总是获胜。
如果您不派生编解码器(因为 CirceEnum
trait 已经提供了现有的实现),那么它将按您的预期工作。
此外,而不是这样做:
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
}
我有一个简单的案例 class 像这样:
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 之类的功能。
这是你的错误:
implicit val columnTypeDecoder: Decoder[AttributeType] = deriveConfiguredDecoder
implicit val columnTypeEncoder: Encoder[AttributeType] = deriveConfiguredEncoder
这将导出新的编解码器,将 AttributeType
视为任何其他密封特征,因此它将使用区分值(半自动总是忽略它们正在导出的类型的现有编解码器!)。
所以你正在派生一个新的 AttributeType
编解码器,将它们放在使用它们的范围内,因此使这些新实现比来自伴随对象的实现具有更高的优先级。越接近隐含总是获胜。
如果您不派生编解码器(因为 CirceEnum
trait 已经提供了现有的实现),那么它将按您的预期工作。
此外,而不是这样做:
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
}