2017-02-13 12 views
0

私は以下のユースケースがあります:私はserde使用JSON4Sフィールド、IDという名前を持っているんだJSON4Sデシリアライゼーション

各クラスを。このIDは任意のタイプT <: Stringifiableになります。StringifiableはIDタイプを文字列にハッシュする必要があります。 Stringifiablesには、文字列から再構築するコンストラクタもあります。

のように、ComplexIdentifierのように、ID: stringified_identifierのJSONにserdeしたいと思います。シリアライゼーションはうまく機能しますが、残念なことにデシリアライズ時にJSON4Sはコンストラクタが1つしかないデフォルトのコンストラクタを使用しません。コンストラクタを検索しますが、識別子の署名がcase class ComplexIdentifier(whatever: String)の場合はwhateverの名前をJString(stringified_identifier)から抽出しようとします。それは失敗し、MappingExceptionが内部的にスローされます。

このような値を抽出せずにデフォルトのコンストラクタを使用するようにJSON4Sを教える方法はありますか? JStringの値を使用して、それを使用してStringifiableを構成することは、とても明らかです。

ありがとうございます!

答えて

0

コンパニオンでapplyメソッドを使用して、IDクラスのコンストラクタに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)) 
それからちょうど次にカスタム・シリアライザを使用して、あなたの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) 

のすべてのカスタム・シリアライザを使用します

関連する問題