diff --git a/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala b/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala new file mode 100644 index 0000000..1f911e2 --- /dev/null +++ b/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala @@ -0,0 +1,37 @@ +package works.iterative.akka + +import akka.serialization.* +import zio.json.* +import scala.reflect.ClassTag + +// Use manifest to ensure the possibility of schema evolution +class AkkaZioJsonSerializer[T <: AnyRef]( + override val identifier: Int, + manifestDiscriminator: T => String +)(using JsonCodec[T])(using ClassTag[T]) + extends SerializerWithStringManifest: + + override def manifest(o: AnyRef): String = + o match + case p: T => manifestDiscriminator(p) + case _ => + throw IllegalArgumentException( + s"Invalid object to serialize, expecting ProofEvent, got: ${o}" + ) + + override def toBinary(o: AnyRef): Array[Byte] = + o match + case p: T => p.toJson.getBytes("UTF-8") + case _ => + throw IllegalArgumentException( + s"Invalid object to serialize, expecting ProofEvent, got: ${o}" + ) + + override def fromBinary(o: Array[Byte], manifest: String): AnyRef = + val json = String(o, "UTF-8") + json.fromJson[T] match + case Left(t) => + throw IllegalStateException( + s"Unable to deserialize ProofEvent from $json: $t" + ) + case Right(e) => e diff --git a/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala b/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala new file mode 100644 index 0000000..1f911e2 --- /dev/null +++ b/akka-persistence/src/main/scala/iw/akka/AkkaZioJsonSerializer.scala @@ -0,0 +1,37 @@ +package works.iterative.akka + +import akka.serialization.* +import zio.json.* +import scala.reflect.ClassTag + +// Use manifest to ensure the possibility of schema evolution +class AkkaZioJsonSerializer[T <: AnyRef]( + override val identifier: Int, + manifestDiscriminator: T => String +)(using JsonCodec[T])(using ClassTag[T]) + extends SerializerWithStringManifest: + + override def manifest(o: AnyRef): String = + o match + case p: T => manifestDiscriminator(p) + case _ => + throw IllegalArgumentException( + s"Invalid object to serialize, expecting ProofEvent, got: ${o}" + ) + + override def toBinary(o: AnyRef): Array[Byte] = + o match + case p: T => p.toJson.getBytes("UTF-8") + case _ => + throw IllegalArgumentException( + s"Invalid object to serialize, expecting ProofEvent, got: ${o}" + ) + + override def fromBinary(o: Array[Byte], manifest: String): AnyRef = + val json = String(o, "UTF-8") + json.fromJson[T] match + case Left(t) => + throw IllegalStateException( + s"Unable to deserialize ProofEvent from $json: $t" + ) + case Right(e) => e diff --git a/codecs/src/main/scala/works/iterative/core/codecs/Codecs.scala b/codecs/src/main/scala/works/iterative/core/codecs/Codecs.scala index a236978..46f4dbe 100644 --- a/codecs/src/main/scala/works/iterative/core/codecs/Codecs.scala +++ b/codecs/src/main/scala/works/iterative/core/codecs/Codecs.scala @@ -20,7 +20,7 @@ def fromValidation[T](v: Validation[UserMessage, T]): Either[String, T] = v.mapError(_.id).toEither.left.map(_.mkString(",")) - private def textCodec[T]( + def textCodec[T]( f: String => Validation[UserMessage, T] ): JsonCodec[T] = JsonCodec.string.transformOrFail(f andThen fromValidation, _.toString) @@ -39,6 +39,8 @@ given JsonCodec[Avatar] = textCodec(Avatar.apply) given JsonCodec[BasicProfile] = DeriveJsonCodec.gen[BasicProfile] + given JsonCodec[FileRef] = DeriveJsonCodec.gen[FileRef] + trait TapirCodecs extends CustomTapir: given Schema[PlainMultiLine] = Schema.string given Schema[PlainOneLine] = Schema.string @@ -49,5 +51,6 @@ given Schema[Avatar] = Schema.string given Schema[Email] = Schema.string given Schema[BasicProfile] = Schema.derived[BasicProfile] + given Schema[FileRef] = Schema.derived[FileRef] object Codecs extends Codecs