GenCodec-style serialization for Scala 3 — a format-agnostic, streaming Input/Output core with type class
derivation built on M&DE. Ships with a JSON backend.
Experimental. Pinned to Scala 3.8.4 (Scala Next), required by Made (
made_3:0.1.2). JVM only.
mcodec is a serialization library in the spirit of AVSystem GenCodec: a
single MCodec[T] type class both reads and writes, and the wire format is decoupled from the codecs. Codecs talk to
an abstract streaming Input/Output, so the same MCodec[T] works across any backend that implements those.
- One type class for read and write —
MCodec[T]withread(input)/write(output, value) - Format-agnostic core — codecs target a streaming
Input/Output; the JSON backend is just one implementation - Automatic derivation —
derives MCodecfor case classes, enums, and sealed hierarchies, powered by M&DE mirrors - Annotation-aware —
@nameto rename fields and ADT cases on the wire,@flatten/@defaultCasefor ADTs - Combinators —
transform,transformed,nullable, andmakeLazyfor building codecs from existing ones - Explicit nulls — compiled with
-Yexplicit-nulls; nullability is expressed in the types
Built-in codecs cover the primitives, BigInt/BigDecimal, UUID, Option, Either, tuples, and the common
collections (List, Vector, Seq, Set, Map).
mcodec has not had its first release yet. The coordinates below are how it will be published to Maven Central under
io.github.halotukozakonce tagged. Until then, build from source (see Build).
//> using scala 3.8.4
//> using dep io.github.halotukozak::mcodec::<version>scalaVersion := "3.8.4"
libraryDependencies += "io.github.halotukozak" %% "mcodec" % "<version>"def scalaVersion = "3.8.4"
def mvDeps = Seq(mvn"io.github.halotukozak::mcodec::<version>")Derive an MCodec for a case class and round-trip it through JSON.
import mcodec.*
case class User(name: String, age: Int) derives MCodec
val json = Json.write(User("Alice", 30)) // {"name":"Alice","age":30}
val user = Json.read[User](json) // User("Alice", 30)Rename fields and ADT cases on the wire with @name:
import mcodec.*
import made.annotation.name
case class User(@name("user_name") name: String, age: Int) derives MCodec
enum Shape derives MCodec:
@name("circ") case Circle(radius: Double)
Json.write(User("bob", 30)) // {"user_name":"bob","age":30}
Json.write[Shape](Shape.Circle(2.0)) // {"circ":{"radius":2.0}}Build codecs from existing ones with the combinators on MCodec:
import mcodec.*
opaque type Email = String
given MCodec[Email] = MCodec[String].transform(identity, identity)
val nullableInt: MCodec[Int | Null] = MCodec[Int].nullablescala-cli --power compile .
scala-cli --power test .
scala-cli --power fmt .mcodec is inspired by the AVSystem commons by **ghik
**, whose GenCodec is the model for the codec design