Configuration Decoders

Configuration decoders are represented in Ciris with ConfigDecoders and provide the ability to decode the value of a ConfigEntry to a different type, while handling errors. ConfigDecoders have access to the whole ConfigEntry to be able to provide sensible error messages, even though only the value is being decoded. ConfigDecoders generally require that a Monad instance is available for the context F of the ConfigEntry, in order to support most decoders. Following is a simplified definition of ConfigDecoder for reference.

import ciris.{ConfigEntry, ConfigError}
import ciris.api.Monad

{
  abstract class ConfigDecoder[A, B] {
    def decode[F[_]: Monad, K, S](
      entry: ConfigEntry[F, K, S, A]
    ): F[Either[ConfigError, B]]
  }
}

Most ConfigDecoders provided by Ciris support decoding from String, but there is nothing preventing you from creating decoders for other types. ConfigDecoder has several combinators helping you create new decoders from existing ones, and the companion object of ConfigDecoder provides several functions for helping you create new decoders. The supporting new types section provides more information on how to create decoders for new types. For currently support types, instead refer to the current supported types section.

ConfigDecoders are most often used indirectly via decodeValue on ConfigEntry. For example, if we take a look at the env function for reading and decoding environment variables, we’ll see that it simply reads the environment variable from ConfigSource.Environment and then decodes the value with decodeValue.

import ciris.{ConfigDecoder, ConfigSource}
import ciris.api.Id

{
  def env[Value](key: String)(
    implicit decoder: ConfigDecoder[String, Value]
  ): ConfigEntry[Id, String, String, Value] = {
    ConfigSource.Environment
      .read(key)
      .decodeValue[Value]
  }
}