我有以下用例:
我使用JSON4S服务的每个类都有一个名为ID
的字段。这个ID
可以是任何类型的T <: Stringifiable
,其中Stringifiable
要求您的ID类型被散列为字符串。 Stringifiables还有构造函数,可以从字符串重构它们。
我想把任何Stringifiable
,例如ComplexIdentifier
加入到ID: stringified_identifier
的JSON中。序列化很好地工作,但不幸的是在反序列化期间,JSON4S不会使用只有1个字符串构造函数的默认构造函数。它找到构造函数,但如果标识符有case class ComplexIdentifier(whatever: String)
的签名,它会尝试从whatever
中提取JString(stringified_identifier)
名称。那失败了,所以MappingException
被内部抛出。
有没有办法教JSON4S使用默认构造函数而不提取像这样的值?只使用JString
中的值并使用它来构造Stringifiable
是显而易见的。
谢谢!
使用Companion中的apply
method使用String参数重载ID类的构造函数。然后只需为所有ID类型使用自定义序列化程序
sealed abstract class Stringifiable {}
case class ComplexIdentifier(whatever: List[Long]) extends Stringifiable
case class SimpleIdentifier(whatever: Int) extends Stringifiable
//Overload the default constructor
object ComplexIdentifier {
def apply(s: String):ComplexIdentifier = {
ComplexIdentifier(s.split(",").map(_.toLong).toList)
}
}
case class MyClass(id: ComplexIdentifier, value: String)
然后使用自定义序列化程序:
case object ComplexIdentifierSerializer extends CustomSerializer[ComplexIdentifier] ( formats =>
({
case JString(id) => ComplexIdentifier(id)
case JNull => null
},
{
case x: ComplexIdentifier => JString(x.whatever.mkString(","))
}))
最后,确保以隐式格式包含序列化程序:
implicit val formats = DefaultFormats ++ List(ComplexIdentifierSerializer)
println(parse("""
{
"id": "1",
"value": "big value"
}
""").extract[MyClass])
val c = MyClass(ComplexIdentifier("123,456"), "super value")
println(write(c))