Jackson-based JSON and CBOR serialization capabilities for the Akka toolkit, enabling efficient serialization and deserialization of Akka messages and persistent events.
—
Akka Serialization Jackson provides built-in serialization support for Akka-specific types through specialized Jackson modules. These modules handle the complexities of serializing distributed system references and Akka-specific data types.
The comprehensive module that includes support for all core Akka types.
/**
* Complete module with support for all custom serializers.
* Includes ActorRef, Address, and FiniteDuration serialization.
*/
class AkkaJacksonModule extends JacksonModule
with ActorRefModule with AddressModule with FiniteDurationModule {
override def getModuleName = "AkkaJacksonModule"
}
object AkkaJacksonModule extends AkkaJacksonModuleModule for Akka Typed ActorRef serialization support.
/**
* Module for Akka Typed ActorRef serialization.
* Only available if akka-actor-typed is on the classpath.
*/
class AkkaTypedJacksonModule extends JacksonModule with TypedActorRefModule {
override def getModuleName = "AkkaTypedJacksonModule"
}
object AkkaTypedJacksonModule extends AkkaTypedJacksonModuleModule for Akka Streams reference serialization.
/**
* Module for Akka Streams serialization (SourceRef, SinkRef).
* Only available if akka-streams is on the classpath.
*/
class AkkaStreamJacksonModule extends JacksonModule with StreamRefModule {
override def getModuleName = "AkkaStreamJacksonModule"
}
object AkkaStreamJacksonModule extends AkkaStreamJacksonModuleClassic ActorRef references are serialized as strings using their serialization format.
import akka.actor.{ActorRef, ActorSystem}
// ActorRef is automatically serialized to string format
val myActor: ActorRef = system.actorOf(Props[MyActor], "myActor")
// JSON representation:
// "akka://MySystem@hostname:2552/user/myActor"Serialization behavior:
ActorRef.path.toSerializationFormatWithAddress()Akka Typed ActorRef instances are serialized using the ActorRefResolver.
import akka.actor.typed.{ActorRef, ActorSystem}
import akka.actor.typed.scaladsl.Behaviors
// Typed ActorRef is automatically serialized
val typedActor: ActorRef[String] =
system.systemActorOf(Behaviors.receiveMessage[String](msg => Behaviors.same), "typedActor")
// JSON representation:
// "akka://MySystem@hostname:2552/system/typedActor#1234567890"Serialization behavior:
ActorRefResolver.toSerializationFormat()Akka Address instances are serialized as URI strings.
import akka.actor.{Address, AddressFromURIString}
val address = Address("akka", "MySystem", "hostname", 2552)
// JSON representation:
// "akka://MySystem@hostname:2552"Serialization behavior:
Address.toString() for serializationAddressFromURIString() for deserializationScala FiniteDuration instances are serialized using Java 8 time format.
import scala.concurrent.duration._
val duration = 30.seconds
// JSON representation (ISO-8601 duration format):
// "PT30S"Serialization behavior:
DurationSerializer from jackson-modules-java8FiniteDuration and Java DurationAkka Streams SourceRef and SinkRef are serialized using StreamRefResolver.
import akka.stream.{SourceRef, SinkRef}
import akka.stream.scaladsl.{Source, Sink}
// SourceRef serialization
val sourceRef: SourceRef[String] = Source(1 to 100).map(_.toString).runWith(StreamRefs.sourceRef())
// SinkRef serialization
val sinkRef: SinkRef[String] = StreamRefs.sinkRef[String]().run()
// JSON representations:
// SourceRef: "sourceRef://MySystem@hostname:2552/temp/$a#1234567890"
// SinkRef: "sinkRef://MySystem@hostname:2552/temp/$b#0987654321"Serialization behavior:
StreamRefResolver.toSerializationFormat() for serializationStreamRefResolver.resolveSourceRef() / resolveSinkRef() for deserializationThe Jackson modules are automatically registered based on classpath detection:
akka.serialization.jackson {
jackson-modules += "akka.serialization.jackson.AkkaJacksonModule"
# Conditionally loaded if akka-actor-typed is available
jackson-modules += "akka.serialization.jackson.AkkaTypedJacksonModule"
# Conditionally loaded if akka-streams is available
jackson-modules += "akka.serialization.jackson.AkkaStreamJacksonModule"
}For custom ObjectMapper instances:
import akka.serialization.jackson._
import com.fasterxml.jackson.databind.ObjectMapper
val mapper = new ObjectMapper()
// Register individual modules
mapper.registerModule(AkkaJacksonModule)
mapper.registerModule(AkkaTypedJacksonModule)
mapper.registerModule(AkkaStreamJacksonModule)
// Or register through custom factory
class MyObjectMapperFactory extends JacksonObjectMapperFactory {
override def overrideConfiguredModules(bindingName: String, configuredModules: Seq[Module]): Seq[Module] = {
configuredModules ++ Seq(
AkkaJacksonModule,
AkkaTypedJacksonModule,
AkkaStreamJacksonModule
)
}
}import akka.actor.ActorRef
case class MessageWithActorRef(text: String, replyTo: ActorRef)
// Usage
val message = MessageWithActorRef("Hello", sender())
// JSON output:
// {
// "text": "Hello",
// "replyTo": "akka://MySystem@hostname:2552/user/sender#1234567890"
// }import scala.concurrent.duration._
case class TimedEvent(name: String, duration: FiniteDuration, timestamp: Long)
// Usage
val event = TimedEvent("processing", 5.minutes, System.currentTimeMillis())
// JSON output:
// {
// "name": "processing",
// "duration": "PT5M",
// "timestamp": 1640995200000
// }import akka.stream.{SourceRef, SinkRef}
case class StreamingJob(id: String, dataSource: SourceRef[String], resultSink: SinkRef[String])
// Usage - when serialized, refs become strings that can be resolved remotely
val job = StreamingJob("job-123", sourceRef, sinkRef)
// JSON output:
// {
// "id": "job-123",
// "dataSource": "sourceRef://MySystem@hostname:2552/temp/$a#1234567890",
// "resultSink": "sinkRef://MySystem@hostname:2552/temp/$b#0987654321"
// }import akka.actor.typed.ActorRef
case class Request(data: String, replyTo: ActorRef[Response])
case class Response(result: String)
// The typed ActorRef maintains type information in the serialized form
val request = Request("process this", typedResponseActor)import akka.actor.typed.{ActorSystem, SpawnProtocol}
val system: ActorSystem[SpawnProtocol.Command] = ActorSystem(Behaviors.setup[SpawnProtocol.Command] { ctx =>
SpawnProtocol()
}, "MySystem")
// System actors are serialized with system path
val systemActor = system.systemActorOf(myBehavior, "systemService")All Akka type deserializers require access to the current ActorSystem:
import akka.serialization.Serialization
// The current ActorSystem is available during deserialization
// through Serialization.currentTransportInformation
val currentSystem = Serialization.currentTransportInformation.value.systemNote: This context is automatically managed by Akka's serialization system and doesn't require manual setup.
// If an ActorRef path cannot be resolved during deserialization:
// - For classic ActorRef: returns deadLetters ActorRef
// - For typed ActorRef: may throw exception depending on resolver configuration// If akka-actor-typed is not on the classpath:
// - AkkaTypedJacksonModule will not be loaded
// - Typed ActorRef serialization will not be available
// If akka-streams is not on the classpath:
// - AkkaStreamJacksonModule will not be loaded
// - StreamRef serialization will not be availableInstall with Tessl CLI
npx tessl i tessl/maven-com-typesafe-akka--akka-serialization-jackson