2017-02-13 61 views
0

我有以下的用例:JSON4S反序列化不帶參數的名字

每一個類,我使用SERDE JSON4S有一個字段,名爲ID。這ID可以是任何類型T <: Stringifiable,其中Stringifiable要求您的ID類型被散列爲一個字符串。 Stringifiables也有構造函數,它們從字符串中重建它們。

我想將任何Stringifiable,例如ComplexIdentifier塞滿到JSON ID: stringified_identifier。序列化很好地工作,但不幸的是,在反序列化過程中,JSON4S不會使用只有1個字符串構造函數的默認構造函數。它找到構造函數,但是如果標識符的簽名爲case class ComplexIdentifier(whatever: String),它將嘗試從JString(stringified_identifier)中提取whatever名稱。這失敗了,所以MappingException被內部拋出。

有什麼辦法教JSON4S使用默認構造函數而不提取這樣的值嗎?只要使用JString的值並使用它構造Stringifiable就顯而易見了。

謝謝!

回答

0

在Companion中使用apply方法可以使用String參數爲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))