我们的状态定义为:
sealed trait Status
case object Status {
case object StatusA extends Status
case object StatusB extends Status
case object StatusC extends Status
}
我们的状态如下:
val status = Status.StatusA
有没有办法用预定义的
json4s
来(反)序列化那种结构?格式化者?我们尝试使用默认的格式化程序,例如:
implicit val formats = new org.json4s.DefaultFormats
它没有用。接下来我们尝试使用
ext
由 json4s
提供使用枚举支持:implicit val formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(Status)
它没有再次工作。我们不得不彻底改变
sealed trait
的结构实际Enumeration
s。有什么办法可以用 case class
是吗?
最佳答案
这是一个完整的工作示例,我稍微更改了您的类以使示例更简单,这样您就可以以不同的方式使用“名称”,实际上可以省略“定义名称”,但在这种情况下,您需要更改序列化器有点。第二个序列化程序就在下面。
sealed trait Status {
def name: String
}
case object Status {
def apply(name: String): Status = name match {
case StatusA.name => StatusA
case StatusB.name => StatusB
case StatusC.name => StatusC
case _ => throw new UnsupportedOperationException("Unknown value")
}
}
case object StatusA extends Status {
override val name = "StatusA"
}
case object StatusB extends Status {
override val name = "StatusB"
}
case object StatusC extends Status {
override val name = "StatusC"
}
class StatusSerializer extends CustomSerializer[Status](formats =>
( {
case JString(s) => Status(s)
case JNull => throw new UnsupportedOperationException("No status specified")
}, {
case status: Status => JString(status.name)
})
)
case class SimpleRichObject(someString: String, someInt: Int, statuses: List[Status])
object Test extends App {
implicit val formats = DefaultFormats + new StatusSerializer
val obj = SimpleRichObject("Answer to life the universe and everything", 42, List(StatusA, StatusB, StatusC))
def toCompactJsonString(any: Any) = {
JsonMethods.compact(JsonMethods.render(Extraction.decompose(any)))
}
def toPrettyJsonString(any: Any) = {
JsonMethods.pretty(JsonMethods.render(Extraction.decompose(any)))
}
/** To Json */
println(s"Compact json:\n${toCompactJsonString(obj)}")
println(s"Pretty json:\n${toPrettyJsonString(obj)}")
/** From Json */
val json =
"""{
| "someString":"Here is a another String",
| "someInt":1234,
| "statuses":["StatusA","StatusB"]
|}""".stripMargin
val richObj = JsonMethods.parse(json).extract[SimpleRichObject]
println(s"Rich object toString: $richObj")
}
这是第二个序列化程序,通过使用第二个序列化程序,您无需在“枚举”中定义额外的代码
class SecondStatusSerializer extends CustomSerializer[Status](formats =>
( {
case JString(s) => s match {
case "StatusA" => StatusA
case "StatusB" => StatusB
case "StatusC" => StatusC
}
case JNull => throw new UnsupportedOperationException("No status specified")
}, {
case status: Status => status match {
case StatusA => JString("StatusA")
case StatusB => JString("StatusB")
case StatusC => JString("StatusC")
}
})
)
这是运行时的外观,紧凑的 json:
{"someString":"Answer to life the universe and everything","someInt":42,"statuses":["StatusA","StatusB","StatusC"]}
漂亮的json:
{
"someString":"Answer to life the universe and everything",
"someInt":42,
"statuses":["StatusA","StatusB","StatusC"]
}
富对象 toString: SimpleRichObject(这里是另一个 String,1234,List(StatusA, StatusB))
关于Scala json4s 密封特征作为枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31135383/