Serialização personalizada de json de classes de casos de escala estruturados

Eu tenho algum código de módulo jackson scala trabalhando para roundtripping classes de caso scala. Jackson funcionou muito bem para as classes de casos simples, mas quando eu fiz uma que contém uma lista de outras classes de casos, a quantidade de código que eu parecia precisar era muito. Considerar:

abstract class Message
case class CardDrawn(player: Long, card: Int, mType: String = "CardDrawn") extends Message
case class CardSet(cards: List[CardDrawn], mType: String = "CardSet") extends Message

Para obter o CardSet para ida e volta de / para json com o módulo jackson scala, usei um serializador / desserializador personalizado escrito em java:

object ScrumGameMashaller {

  val mapper = new ObjectMapper() 
  val module = new SimpleModule("CustomSerializer")
  module.addSerializer(classOf[CardSet], new CardSetSerializer)
  module.addDeserializer(classOf[CardSet], new CardSetDeserializer)
  val scalaModule = DefaultScalaModule
  mapper.registerModule(scalaModule)
  mapper.registerModule(module)

  def jsonFrom(value: Any): String = {
    import java.io.StringWriter
    val writer = new StringWriter()
    mapper.writeValue(writer, value)
    writer.toString
  }

  private[this] def objectFrom[T: Manifest](value: String): T =
    mapper.readValue(value, typeReference[T])

  private[this] def typeReference[T: Manifest] = new TypeReference[T] {
    override def getType = typeFromManifest(manifest[T])
  }

  private[this] def typeFromManifest(m: Manifest[_]): Type = {
    if (m.typeArguments.isEmpty) { m.runtimeClass }
    else new ParameterizedType {
      def getRawType = m.runtimeClass
      def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
      def getOwnerType = null
    }
  }

com serializador:

public class CardSetSerializer extends JsonSerializer<CardSet> {
@Override
    public void serialize(CardSet cardSet, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeArrayFieldStart("cards");
        List<CardDrawn> cardsDrawn = cardSet.cards();
        scala.collection.Iterator<CardDrawn> iter = cardsDrawn.iterator();
        while(iter.hasNext()){
            CardDrawn cd = iter.next();
            cdSerialize(jgen,cd);
        }
        jgen.writeEndArray();
        jgen.writeStringField("mType", "CardSet");
        jgen.writeEndObject();      
    }

    private void cdSerialize(JsonGenerator jgen, CardDrawn cd) throws IOException, JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("player", cd.player());
        jgen.writeNumberField("card", cd.card());
        jgen.writeEndObject();
    }
}

e desserializador correspondente:

public class CardSetDeserializer extends JsonDeserializer<CardSet> {

    private static class CardDrawnTuple {
        Long player;
        Integer card;
    }

    @Override
    public CardSet deserialize(JsonParser jsonParser, DeserializationContext cxt) throws IOException, JsonProcessingException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode root = oc.readTree(jsonParser);
        JsonNode cards = root.get("cards");
        Iterator<JsonNode> i = cards.elements();
        List<CardDrawn> cardObjects = new ArrayList<>();
        while( i.hasNext() ){
            CardDrawnTuple t = new CardDrawnTuple();
            ObjectNode c = (ObjectNode) i.next();
            Iterator<Entry<String, JsonNode>> fields = c.fields();
            while( fields.hasNext() ){
                Entry<String,JsonNode> f = fields.next();
                if( f.getKey().equals("player")) {
                    t.player = f.getValue().asLong();
                } else if( f.getKey().equals("card")){
                    t.card = f.getValue().asInt();
                } else { 
                    System.err.println(CardSetDeserializer.class.getCanonicalName()+ " : unknown field " + f.getKey());
                }
            }
            CardDrawn cd = new CardDrawn(t.player, t.card, "CardDrawn");
            cardObjects.add(cd);
        }

        return new CardSet(JavaConversions.asScalaBuffer(cardObjects).toList(), "CardSet");
    }

}

Este parece ser um código muito para lidar com algo bastante baunilha na scala. Esse código pode ser melhorado (o que eu senti falta que o jackson tem para facilitar isso)? Existe outra biblioteca que fará automaticamente as classes de casos estruturados? Os exemplos de jerkson pareciam fáceis, mas isso parece ter sido abandonado.

questionAnswers(2)

yourAnswerToTheQuestion