object DeriveConfigDescriptor extends DeriveConfigDescriptor
- Alphabetic
- By Inheritance
- DeriveConfigDescriptor
- DeriveConfigDescriptor
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- type Typeclass[T] = magnolia.Descriptor[T]
- Definition Classes
- DeriveConfigDescriptor
Deprecated Type Members
- type Descriptor[T] = magnolia.Descriptor[T]
- Annotations
- @deprecated
- Deprecated
(Since version 1.0.1) Use zio.config.magnolia.Descriptor[T] directly
Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native()
- final def combine[T](caseClass: CaseClass[magnolia.Descriptor, T]): magnolia.Descriptor[T]
- Definition Classes
- DeriveConfigDescriptor
- def descriptor[T](implicit config: magnolia.Descriptor[T]): config.ConfigDescriptor[T]
descriptor[A] allows us to automatically derive
ConfigDescriptor
instead of using the ConfigDescriptor dsl explicitly (i.e, manually defining configdescriptor).descriptor[A] allows us to automatically derive
ConfigDescriptor
instead of using the ConfigDescriptor dsl explicitly (i.e, manually defining configdescriptor). While manual definitions can be verbose, it is preferred when it comes to simple configurations.On the other hand, automatic derivation can become handly when the config is complex with relatively larger number of parameters, or when it is constantly changing during the software lifecycle, or it's just complex structure with nested products and coproducts. Also, when building configuration driven apps, most probably we might end up mixing manual and automatic together.
Below given is a small example to show the usage of
descriptor[A]
.Example :
final case class MyConfig(appName: String, port: Int, jdbcUrl: String) val configDesc: ConfigDescriptor[MyConfig] val config = read(configDesc from ConfigSource.fromMap(Map.empty))
descriptor[MyConfig]
works only if all the types that formsMyConfig
has an instance ofDescriptor
. For almost all the important types, zio-config-magnolia already provides implicit instances forDescriptor
.However, say you have a type ZonedDateTime, for which zio-config hasn't provided instance of
Descriptor
, then it will fail to compile.case class MyConfig(x: ZonedDateTime)
In this case, define a Descriptor for ZonedDateTime using
implicit def deriveForZonedDateTime: Descriptor[ZonedDateTime] = Descriptor[String].transformOrFail(string => Try(ZonedDateTime.parse(string).toEither.swap.map(_.getMessage).swap, r => Right(r.toString)) descriptor[MyConfig] // then works
descriptor[A]
can also handle sealed traits, maps list etc.Example:
sealed trait A object A { case class B(x: String, y: String) extends A case class C(z: String) extends A case object D extends A } val config = descriptor[A] val mapSource = ConfigSource.fromMap(Map("B.x" -> "l", "B.y" -> "m") val result = read(config from mapSource) // Right(B("x", "y")) val typesafeSource = TypesafeConfigSource.fromHoconString( s""" { B : { x : l y : m } } """ val result = typesafeSource.flatMap(source => read(config from source)) // Right(B("x", "y")) )
While sealed trait can be fairly straight forward, there are historical errors users make with any advanced config libraries.
Example: What happens if there is another
B
in the same package but for a different parent sealed trait name ?sealed trait X object X { case class B(x: String, y: String) extends X case class C(z: String) extends X case object D extends X } sealed trait Y object Y { case class B(x: String, y: String) extends Y case class Z(value: String) extends Y } final case class MyConfig(xOrY: Either[X, Y]) val typesafeSource = TypesafeConfigSource.fromHoconString( s""" xOrY: { B : { x : l, y : m } } """ )
For zio-config, Either[X, Y] implies, it tries to fetch X and if it fails, it falls over to trying to read Y.
However, in the above case, the output will be always X while user might have intended to provide Y.
This was just an example, but similar conflicts can occur and zio-config-magnolia has strong semantics to handle such scenarios. The best way is to indicate the name of the sealed trait itself.
That is
Example:
import zio.config._ // This implies, not only we are making use of the names of the case classes (or case objects) but the actual // name of the sealed trait as well. val betterDerivation = new DeriveConfigDescriptor { override def sealedTraitStrategy: Descriptor.SealedTraitStrategy = wrapSubClassName && wrapSealedTraitName }
If the source is HOCON, then
betterDerivation.descriptor[MyConfig]
can read:
xOrY: { X : { B : { x : xyz y : xyz } } }
Providing the name of the sealed traits is least commonly used. This is why the default derivation of sealed trait doesn't consider it.
There is a third way of config derivation, especially for those who would like to migrate pure-config's implementation. In this case, we ignore the sealed-trait name, but we consider the sub-class name but not as a parent but part of the product itself.
import zio.config._ val customDerivation = new DeriveConfigDescriptor { override def sealedTraitStrategy: Descriptor.SealedTraitStrategy = labelSubClassName("type") && ignoreSealedTraitName }
If the source is HOCON, then
customDerivation.descriptor[MyConfig]
can read:
x: { type : B x : r y : z }
customDerivation.descriptor[MyConfig] }}}
x: { type : B x : r y : z }
betterDerivation.descriptor[MyConfig] }}}
xOrY: { X : { B : { x : xyz y : xyz } } }
Providing the name of the sealed traits is least commonly used. This is why the default derivation of sealed trait doesn't consider it.
There is a third way of config derivation, especially for those who would like to migrate pure-config's implementation. In this case, we ignore the sealed-trait name, but we consider the sub-class name but not as a parent but part of the product itself.
import zio.config._ val customDerivation = new DeriveConfigDescriptor { override def sealedTraitStrategy: Descriptor.SealedTraitStrategy = labelSubClassName("type") && ignoreSealedTraitName }
If the source is HOCON, then
customDerivation.descriptor[MyConfig]
can read:
x: { type : B x : r y : z }
customDerivation.descriptor[MyConfig] }}}
x: { type : B x : r y : z }
- Definition Classes
- DeriveConfigDescriptor
- final def dispatch[T](sealedTrait: SealedTrait[magnolia.Descriptor, T]): magnolia.Descriptor[T]
- Definition Classes
- DeriveConfigDescriptor
- def eitherDesc[A, B](left: config.ConfigDescriptor[A], right: config.ConfigDescriptor[B]): config.ConfigDescriptor[Either[A, B]]
- Attributes
- protected
- Definition Classes
- DeriveConfigDescriptor
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable])
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- implicit macro def getDescriptor[T]: magnolia.Descriptor[T]
- Definition Classes
- DeriveConfigDescriptor
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- implicit val implicitBigDecimalDesc: magnolia.Descriptor[BigDecimal]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitBigIntDesc: magnolia.Descriptor[BigInt]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitBooleanDesc: magnolia.Descriptor[Boolean]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitByteDesc: magnolia.Descriptor[Byte]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitDoubleDesc: magnolia.Descriptor[Double]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitDurationDesc: magnolia.Descriptor[zio.Duration]
- Definition Classes
- DeriveConfigDescriptor
- implicit def implicitEitherDesc[A, B](implicit arg0: magnolia.Descriptor[A], arg1: magnolia.Descriptor[B]): magnolia.Descriptor[Either[A, B]]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitFileDesc: magnolia.Descriptor[File]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitFloatDesc: magnolia.Descriptor[Float]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitInstantDesc: magnolia.Descriptor[Instant]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitIntDesc: magnolia.Descriptor[Int]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitJavaFilePathDesc: magnolia.Descriptor[Path]
- Definition Classes
- DeriveConfigDescriptor
- implicit def implicitListDesc[A](implicit arg0: magnolia.Descriptor[A]): magnolia.Descriptor[List[A]]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitLocalDateDesc: magnolia.Descriptor[LocalDate]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitLocalDateTimeDesc: magnolia.Descriptor[LocalDateTime]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitLocalTimeDesc: magnolia.Descriptor[LocalTime]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitLongDesc: magnolia.Descriptor[Long]
- Definition Classes
- DeriveConfigDescriptor
- implicit def implicitMapDesc[K, A](implicit arg0: magnolia.Descriptor[A]): magnolia.Descriptor[Map[String, A]]
- Definition Classes
- DeriveConfigDescriptor
- implicit def implicitOptionDesc[A](implicit arg0: magnolia.Descriptor[A]): magnolia.Descriptor[Option[A]]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitScalaDurationDesc: magnolia.Descriptor[scala.concurrent.duration.Duration]
- Definition Classes
- DeriveConfigDescriptor
- implicit def implicitSetDesc[A](implicit arg0: magnolia.Descriptor[A]): magnolia.Descriptor[Set[A]]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitShortDesc: magnolia.Descriptor[Short]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitStringDesc: magnolia.Descriptor[String]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitUUIDDesc: magnolia.Descriptor[UUID]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitUriDesc: magnolia.Descriptor[URI]
- Definition Classes
- DeriveConfigDescriptor
- implicit val implicitUrlDesc: magnolia.Descriptor[URL]
- Definition Classes
- DeriveConfigDescriptor
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- def listDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[List[A]]
- Attributes
- protected
- Definition Classes
- DeriveConfigDescriptor
- def mapClassName(name: String): String
Strategy on how to name the class names in the source config (if they are used in the config) By default, zio-config doesn't make assumptions that config keys or class names, especially when there is sealed traits or case objects
Strategy on how to name the class names in the source config (if they are used in the config) By default, zio-config doesn't make assumptions that config keys or class names, especially when there is sealed traits or case objects
Example:
sealed trait Credentials object Credentials { final case class UsernamePassword(username: String, password: String) extends Credentials final case class Token(username: String, tokenId: String) extends Credentials. } final case class MyConfig(auth: Credentials)
Given:
import zio.config._ val customDerivation = new DeriveConfigDescriptor { override def mapClassName(name: String): String = toKebabCase(name) } // Usage: customDerivation.descriptor[MyConfig]
If the source is HOCON, then
customDerivation.descriptor[MyConfig]
can read:
auth : { username-password : { username : xyz password : abc } }
Alternative solution:
sealed trait Credentials @name("username-password") case class UsernamePassword(username: String, password: String) extends Credentials @name("token") case class Token(username: String, tokenId: String) extends Credentials.
With the above structure, if the source is HOCON, then
descriptor[Credentials]
can read:
auth : { username-password : { username : xyz password : abc } }
The latter solution is more specific to each sealed traits.
descriptor[Credentials] }}}
auth : { username-password : { username : xyz password : abc } }
The latter solution is more specific to each sealed traits.
customDerivation.descriptor[MyConfig] }}}
auth : { username-password : { username : xyz password : abc } }
Alternative solution:
sealed trait Credentials @name("username-password") case class UsernamePassword(username: String, password: String) extends Credentials @name("token") case class Token(username: String, tokenId: String) extends Credentials.
With the above structure, if the source is HOCON, then
descriptor[Credentials]
can read:
auth : { username-password : { username : xyz password : abc } }
The latter solution is more specific to each sealed traits.
descriptor[Credentials] }}}
auth : { username-password : { username : xyz password : abc } }
The latter solution is more specific to each sealed traits.
- Definition Classes
- DeriveConfigDescriptor
- def mapDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Map[String, A]]
- Attributes
- protected
- Definition Classes
- DeriveConfigDescriptor
- def mapFieldName(name: String): String
Strategy on how to name the field names in the actual config
Strategy on how to name the field names in the actual config
val customDerivation = new DeriveConfigDescriptor { override def mapFieldName(name: String): String = name.toUpperCase } // Usage: customDerivation.descriptor[MyConfig]
Given,
sealed trait Credentials object Credentials { final case class UsernamePassword(username: String, password: String) extends Credentials final case class Token(username: String, tokenId: String) extends Credentials. } final case class MyConfig(auth: Credentials)
If the source is HOCON, then
customDerivation.descriptor[MyConfig]
can read:
auth : { username_password : { USERNAME : xyz PASSWORD : abc } }
customDerivation.descriptor[MyConfig] }}}
auth : { username_password : { USERNAME : xyz PASSWORD : abc } }
- Definition Classes
- DeriveConfigDescriptor
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- def optionDesc[A](configDesc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Option[A]]
- Attributes
- protected
- Definition Classes
- DeriveConfigDescriptor
- final def prepareClassName(annotations: Seq[Any], name: String): String
- Definition Classes
- DeriveConfigDescriptor
- final def prepareClassNames(annotations: Seq[Any], name: String): Seq[String]
- Definition Classes
- DeriveConfigDescriptor
- final def prepareFieldName(annotations: Seq[Any], name: String): String
- Definition Classes
- DeriveConfigDescriptor
- final def prepareFieldNames(annotations: Seq[Any], name: String): Seq[String]
- Definition Classes
- DeriveConfigDescriptor
- def sealedTraitStrategy: SealedTraitStrategy
- Definition Classes
- DeriveConfigDescriptor
- def setDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Set[A]]
- Attributes
- protected
- Definition Classes
- DeriveConfigDescriptor
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()
- final def wrapSealedTrait[T](labels: Seq[String], desc: config.ConfigDescriptor[T]): config.ConfigDescriptor[T]
- Definition Classes
- DeriveConfigDescriptor
Deprecated Value Members
- val Descriptor: magnolia.Descriptor.type
- Annotations
- @deprecated
- Deprecated
(Since version 1.0.1) Use zio.config.magnolia.Descriptor directly