结构化scala案例类的自定义json序列化
发布时间:2020-12-16 18:28:08 所属栏目:安全 来源:网络整理
导读:我有一些工作杰克逊 scala模块代码用于往返 scala案例类.杰克逊在平面案例课程中工作得非常好,但是当我创建一个包含其他案例类别的列表时,我似乎需要的代码量很多.考虑: abstract class Messagecase class CardDrawn(player: Long,card: Int,mType: String
我有一些工作杰克逊
scala模块代码用于往返
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 为了让CardSet与jackson scala模块一起往返于json,我使用了一个用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 } } 使用序列化器: 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(); } } 和匹配的反序列化器: 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"); } } 这似乎是很多代码来处理scala中相当普通的东西.这段代码可以改进吗(我想念杰克逊必须做些什么)?否则有一个库会自动执行结构化案例类? jerkson的例子看起来很简单,但似乎已经放弃了. 解决方法
Argonaut做得很好.
Mark Hibbard帮我解决了下面的例子.所需要的只是为类型创建一个编解码器,它会隐式地将asJson添加到您的对象中以将它们转换为字符串.它还会将一个decodeOption [YourClass]添加到字符串中以提取对象.下列:
package argonaut.example import argonaut._,Argonaut._ abstract class Message case class CardDrawn(player: Long,mType: String = "CardSet") extends Message object CardSetExample { implicit lazy val CodecCardSet: CodecJson[CardSet] = casecodec2(CardSet.apply,CardSet.unapply)("cards","mType") implicit lazy val CodecCardDrawn: CodecJson[CardDrawn] = casecodec3(CardDrawn.apply,CardDrawn.unapply)("player","card","mType") def main(args: Array[String]): Unit = { val value = CardSet(List(CardDrawn(1L,2),CardDrawn(3L,4))) println(s"Got some good json ${value.asJson}") val jstring = """{ | "cards":[ | {"player":"1","card":2,"mType":"CardDrawn"},| {"player":"3","card":4,"mType":"CardDrawn"} | ],| "mType":"CardSet" | }""".stripMargin val parsed: Option[CardSet] = jstring.decodeOption[CardSet] println(s"Got a good object ${parsed.get}") } } 输出: 得到了一些好的json {“牌”:[{“player”:“1”,“card”:2,“mType”:“CardDrawn”},{“player”:“3”,“card”:4,“ MTYPE “:” CardDrawn “}],” MTYPE “:” CardSet“} 有一个好的对象CardSet(List(CardDrawn(1,2,CardDrawn),CardDrawn(3,4,CardDrawn)),CardSet) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |