#scala #serialization #sbt #deserialization #ammonite
#scala #сериализация #sbt #десериализация #аммонит
Вопрос:
Итак, у меня есть такой объект
case class QueryResult(events: List[Event])
что мне нужно сериализовать десериализацию. Для сериализации у меня есть этот неявный класс
implicit class Serializer(obj: Object) {
def serialize: Array[Byte] = {
val stream = new ByteArrayOutputStream()
val objectOutputStream = new ObjectOutputStream(stream)
objectOutputStream.writeObject(obj)
objectOutputStream.close
stream.toByteArray
}
}
Он используется как
val byteArray = QueryResult(events).serialize
Тогда для десриализации у меня есть эта черта, которая может быть расширена сопутствующим классом.
trait Deserializer[A] {
private type resultType = A
def deserialize(bytes: Array[Byte]): A = {
val objectInputStream = new ObjectInputStream(
new ByteArrayInputStream(bytes)
)
val value = objectInputStream.readObject.asInstanceOf[resultType]
objectInputStream.close
value
}
}
Вы бы использовали его следующим образом
object QueryResult extends Deserializer[QueryResult]
Тогда вы должны иметь возможность восстановить экземпляр QueryResult
из массива байтов следующим образом
val QueryResult: QueryResult = QueryResult.deserialize(byteArray)
Проблема в том, что это иногда вызывает ошибку, подобную приведенной ниже
java.lang.ClassCastException: cannot assign instance of scala.collection.generic.DefaultSerializationProxy to field co.app.QueryResult.events of type scala.collection.immutable.List in instance of co.app.QueryResult
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2205)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2168)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1422)
at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2450)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2166)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1668)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at co.app.Deserializer.deserialize(Types.scala:51)
at co.app.Deserializer.deserialize$(Types.scala:47)
at co.app.LocalStorage$QueryResults$.get(LocalStorage.scala:241)
... 36 elided
Теперь, когда я говорю «иногда», я имею в виду, что десериализация работает, когда я собираю код в jar и запускаю его с помощью java
cli, но она прерывается, когда я пытаюсь выполнить этот код через sbt test
, sbt console
, или ammonite
. Есть идеи, почему он ломается при таких обстоятельствах, и возможные предложения по исправлению?
Комментарии:
1. Как вы сериализуете объект, который пытаетесь десериализовать? Работает ли это, если вы сериализуете, а затем десериализуете в том же исполнении (т. Е. Что-то вроде
deserialize(serialize(myObject))
)?2. Обратите внимание, что я не знаю вашего варианта использования, но по умолчанию я бы не рекомендовал использовать сериализацию java. Для этого лучше использовать выделенную библиотеку.
3. @juh Ответ на ваш первый вопрос — нет, не всегда. Та же ошибка возникает, когда я пытаюсь выполнить serde в одной строке, но только при определенных обстоятельствах. Код работает нормально, когда я запускаю jar из
java
командной строки. Я обновил сообщение, чтобы объяснить, как я выполняю сериализацию. Возможно, вы правы, переход на выделенную библиотеку может быть правильным решением.