Tôi có một số mã mô-đun scala jackson làm việc để roundtripping các lớp scala case. Jackson làm việc tuyệt vời cho các trường hợp trường hợp bằng phẳng nhưng khi tôi thực hiện một trong đó có một danh sách các trường hợp các lớp khác số lượng mã tôi dường như cần là rất nhiều. Xem xét:Tùy chỉnh tuần tự json của các lớp scala case có cấu trúc
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
Để có được CardSet để khứ hồi đến/từ json với module scala jackson tôi đã sử dụng một serializer tùy chỉnh/deserializer viết bằng 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
}
}
với 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();
}
}
và khớp với 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");
}
}
Điều này có vẻ như rất nhiều mã để đối phó với một cái gì đó khá vani trong scala. Mã này có thể được cải thiện không (tôi đã bỏ lỡ điều gì mà jackson phải làm cho việc này trở nên dễ dàng)? Khác là có một thư viện mà sẽ làm các lớp trường hợp có cấu trúc tự động? Các ví dụ jerkson trông dễ dàng nhưng dường như đã bị bỏ rơi.
tôi đã cố gắng giắc trông đầy hứa hẹn nhưng có một vấn đề với các lớp mà tôi trình bày ở đây https://github.com/ wg/jacks/issues/15 – simbo1905
Argonaut thực hiện công việc chỉ với '' 'CodecCardSet ngầm: CodecJson [CardSet] = casecodec2 (CardSet.apply, CardSet.unapply) (" cards "," mType ")' '' và '' 'CodecCardDrawn lười biếng ẩn: CodecJson [Thẻ Drawn] = casecodec3 (CardDrawn.apply, CardDrawn.unapply) ("trình phát", "thẻ", "mType") '' 'xem ví dụ tại https://github.com/argonaut-io/argonaut/issues/64 – simbo1905
bạn đã cân nhắc sử dụng Mô-đun Scala Jackson chưa? https://github.com/FasterXML/jackson-module-scala –