Ich habe einige Arbeits Jackson Scala-Modul-Code zum Roundtripping Scala Fall Klassen. Jackson arbeitete großartig für flache Fall-Klassen, aber als ich eine erstellte, die eine Liste von anderen Fall-Klassen enthält, war die Menge an Code, den ich zu brauchen schien, eine Menge. Bedenken Sie:Benutzerdefinierte Json-Serialisierung von strukturierten Scala-Fallklassen
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
Um die Cardset zu bekommen Roundtrip zu/von json mit jackson scala Modul ich einen benutzerdefinierten Serializer verwendet/in Java geschrieben Deserializer:
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
}
}
mit Serializer:
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();
}
}
und passender Deserializer:
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");
}
}
Das scheint eine Menge Code zu sein, mit etwas ziemlich Vanille in der Scala umzugehen. Kann dieser Code verbessert werden (was habe ich vermisst, dass Jackson das so einfach machen muss)? Gibt es eine Bibliothek, die automatisch strukturierte Fallklassen durchführt? Die Jerkson-Beispiele sahen einfach aus, aber das scheint aufgegeben worden zu sein.
I-Buchsen versucht, die vielversprechend aussah, hatte aber ein Problem mit diesen Klassen, die ich hier berichten https://github.com/ wg/jacks/issues/15 – simbo1905
Argonaut macht den Job mit nur '' 'implizit lazy val CodecCardSet: CodecJson [CardSet] = casecodec2 (CardSet.apply, CardSet.unapply) (" Karten "," mType ")' '' und '' 'implizite lazy val CodecCardDrawn: CodecJson [Karte Gezeichnet] = casecodec3 (CardDrawn.apply, CardDrawn.unapply) ("player", "card", "mType") '' 'siehe Beispiel unter https://github.com/argonaut-io/argonaut/issues/64 – simbo1905
Haben Sie überlegt, das Scala Jackson Modul zu benutzen? https://github.com/FasterXML/jackson-module-scala –