Ho qualche codice jackson scala module funzionante per arrotondare le classi di case scala. Jackson ha lavorato alla grande per classi di case piatte, ma quando ne ho realizzato uno che contiene un elenco di altre classi di casi la quantità di codice che mi sembrava avesse bisogno era molto. Considerare:Serializzazione json personalizzata di classi di case strutturate scala
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
Per ottenere risultati cardset di andata e ritorno da/per JSON con modulo scala Jackson Ho usato un serializzatore personalizzato/deserializzatore scritto in 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
}
}
con 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();
}
}
e deserializzatore di corrispondenza:
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");
}
}
Questo sembra un codice molto da trattare con qualcosa di abbastanza vanigliato nella scala. Questo codice può essere migliorato (cosa mi è mancato che Jackson abbia reso questo facile)? Altrimenti c'è una libreria che farà automaticamente classi di case strutturate? Gli esempi di jerkson sembravano facili ma sembra essere stato abbandonato.
ho provato martinetti che sembrava promettente, ma avuto un problema con queste classi, che ho riportato qui https://github.com/ wg/jacks/issues/15 – simbo1905
Argonaut fa il lavoro con solo '' 'implicito lazy val CodecCardSet: CodecJson [CardSet] = casecodec2 (CardSet.apply, CardSet.unapply) (" cards "," mType ")' '' e '' 'implicit lazy val CodecCardDrawn: CodecJson [Card Drawn] = casecodec3 (CardDrawn.apply, CardDrawn.unapply) ("player", "card", "mType") '' 'guarda l'esempio su https://github.com/argonaut-io/argonaut/issues/64 – simbo1905
hai preso in considerazione l'utilizzo del modulo Scala Jackson? https://github.com/FasterXML/jackson-module-scala –