问题
We have an "enumeration" like so:
sealed abstract class StatusEnumeration(val value: String)
case object Status {
case object Mine extends StatusEnumeration("mine")
case object Someone extends StatusEnumeration("someone")
case object Neighbor extends StatusEnumeration("neighbor")
case object Unknown extends StatusEnumeration("unknown")
}
This structure is dictated by our domain/needs. However, I'd like to convert this StatusEnumeration
into an output JSON like so:
case class Root(status: StatusEnumeration)
I've set the following implicit encoder and it works as expected:
implicit val encoder = deriveEnumerationEncoder[StatusEnumeration]
However, if the StatusEnumeration
is set to Status.Unknown
I'd like for the value generation to be skipped Or just output a null
instead (which I can then drop via dropNullValues
). How can I do something like this? Is it even possible or do I need to redefine another set of enums?
So far this is what I was trying when @Alec also commented to try something similar:
implicit val encoder = deriveEnumerationEncoder[StatusEnumeration].mapJson(x=>{
x.asString match {
case Some("Unknown") => Json.Null
case Some(s) => Json.fromString(s.toLowerCase) // output expect lowercase - not sure if the consumer is case-sensitive
case None => Json.Null
}
})
This does seem to work as expected. Is this the recommended way or is there a better one?
回答1:
Haven't tried to compile this, but based on the Scaladocs you should be able to do:
implicit val encoder = Encoder.encodeOption(deriveEnumerationEncoder[StatusEnumeration])
.contramap {
case Unknown => None
case known => Some(known)
}
Basically, construct an encoder Option[StatusEnumeration]
, then map StatusEnumeration
onto that accordingly (I'm pretty sure the encoder for Option
puts None
as null
and Some(x)
as x
encoded).
来源:https://stackoverflow.com/questions/55976376/how-to-get-circe-to-skip-certain-values-from-the-enumeration