dhall-generic
                                
                                 dhall-generic copied to clipboard
                                
                                    dhall-generic copied to clipboard
                            
                            
                            
                        Dhall generic decoder for Scala
Dhall Scala Generic
Load Dhall config directly into Scala case class
libraryDependencies += "us.oyanglul" %% "dhall-generic" % "0.3.+"
There is a dhall config
let Shape = <Rectangle: {width: Double, height: Double}| Circle: {radius: Double}>
in Shape.Circle {radius = 1.2}
And you can parse them into dhall Expr
import org.dhallj.syntax._
val expr = """
let Shape = <Rectangle: {width: Double, height: Double}| Circle: {radius: Double}>
in Shape.Circle {radius = 1.2}
""".parseExpr
Scala 3
Supposed that you have some Scala case classes
enum Shape:
  case Rectangle(width: Double, height: Double)
  case Circle(radius: Double)
to load a dhall expr into Scala case classes, simply just
- derives Decoder
import us.oyanglul.dhall.generic.Decoder
enum Shape derives Decoder:  // derive will generate decoder inline
  case Rectangle(width: Double, height: Double)
  case Circle(radius: Double)
- as[Shape]
import us.oyanglul.dhall.generic.as
expr.normalize.as[Shape]
// => Right(Circle(1.2)): Either[DecodingFailure, Shape]
Scala 2
Supposed that you have some Scala case classes
sealed trait Shape
object Shape {
  case class Rectangle(width: Double, height: Double) extends Shape
  case class Circle(radius: Double) extends Shape
}
to load a dhall expr into Scala case classes, simply just
import org.dhallj.codec.syntax._   // for `.as[A]` syntax
import org.dhallj.codec.Decoder._  // Decoders for primity types
import us.oyanglul.dhall.generic._ // generate generic decoders
expr.normalize.as[Shape]
// => Right(Circle(1.2)): Either[DecodingFailure, Shape]
Use cases
Load application config
It is very simple to replace HOCON application.conf with dhall.
To load src/main/resources/application.dhall from classpath your will need dhall-imports
import org.dhallj.syntax._
import org.dhallj.codec.syntax._
import us.oyanglul.dhall.generic._
import org.dhallj.imports.syntax._
  BlazeClientBuilder[IO](ExecutionContext.global).resource.use { implicit c =>
        IO.fromEither("classpath:/application.dhall".parseExpr)
          .flatMap(_.resolveImports[IO])
          .flatMap{expr => IO.fromEither(expr.normalize.as[Config])}
    }
Load dhall to sbt libraryDependencies
This project itself is an example of how to load dhall into build.sbt
It is recursively using previous version to load ./build.dhall to libraryDependencies
libraryDependencies ++= dhall.load.modules.map{case Module(o, n, v) => o %% n % v},
Custom Decoder
Create new decoder from existing decoder
i.e. UUID
Scala 3
given (using d: Decoder[String]): Decoder[UUID] = d.map(UUID.fromString)
Scala 2
implicit val decodeUUID: Decoder[UUID] = decodeString.map(UUID.from)