Chimney
Scala library for boilerplate-free data transformations.
In the daily life of a strongly-typed language's programmer sometimes it happens we need to transform an object of one type to another object which contains a number of the same or similar fields in their definitions.
case class MakeCoffee(id: Int, kind: String, addict: String)
case class CoffeeMade(id: Int, kind: String, forAddict: String, at: ZonedDateTime)
Usual approach is to just rewrite fields one by one
val command = MakeCoffee(id = Random.nextInt,
kind = "Espresso",
addict = "Piotr")
val event = CoffeeMade(id = command.id,
kind = command.kind,
forAddict = command.addict,
at = ZonedDateTime.now)
While the example stays lean, in real-life code we usually end up with tons of such boilerplate, especially when:
- we maintain typed schema and want to migrate between multiple schema versions
- we apply practices like DDD (Domain-Driven-Design) where suggested approach is to separate model schemas of different bounded contexts
- we use code-generation tools like Protocol Buffers that generate primitive types like
Int
orString
, while you'd prefer to use value objects in you domain-level code to improve type-safety and readability
Chimney provides a compact DSL with which you can define transformation rules and transform your objects with as little boilerplate as possible.
import io.scalaland.chimney.dsl._
val event = command.into[CoffeeMade]
.withFieldComputed(_.at, _ => ZonedDateTime.now)
.withFieldRenamed(_.addict, _.forAddict)
.transform
Underneath it uses Scala macros to give you:
- type-safety at compile-time
- fast generated code, almost equivalent to hand-written version
- excellent error messages
- minimal overhead on compilation time
Getting started
To include Chimney to your SBT project, add the following line to your build.sbt
:
libraryDependencies += "io.scalaland" %% "chimney" % "0.6.1"
Library is released for Scala 2.12.x and 2.13.x.
If you want to use it with Scala.js, you need to replace %%
with %%%
. Due to some compiler bugs, it's recommended to use at least Scala 2.12.1.
Trying with Ammonite REPL
The quickest way to try out Chimney is to use a script that downloads coursier and uses it to fetch Ammonite REPL with the latest version of Chimney. It drops you immediately into a REPL session.
curl -s https://raw.githubusercontent.com/scalalandio/chimney/master/try-chimney.sh | bash
Loading...
Welcome to the Ammonite Repl 1.1.0
(Scala 2.12.4 Java 1.8.0_152)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ case class Foo(x: String, y: Int)
defined class Foo
@ case class Bar(x: String, y: Int, z: Boolean = true)
defined class Bar
@ Foo("abc", 10).transformInto[Bar]
res2: Bar = Bar("abc", 10, true)
Documentation
Chimney documentation is available at https://scalalandio.github.io/chimney
Building documentation locally
In order to build documentation locally, you need to install Sphinx documentation generator first.
Then in project's root directory run command:
sbt makeSite
HTML Documentation should be generated at target/sphinx/html/index.html
.
Thanks
Thanks to JProfiler (Java profiler) for helping us develop the library and allowing us to use it during development.