Pure config enum

120 views Asked by At

Pure config can't pars capital letters in conf

  sealed trait Occupation extends Product with Serializable


  object Occupation {
    case class Employed(job: String) extends Occupation

    object Employed {
      implicit val employedReader = deriveReader[Employed]
    }

    case object Unemployed extends Occupation {
      implicit val unemployedReader = deriveReader[Unemployed.type]
    }

    case object Student extends Occupation {
      implicit val studentReader = deriveReader[Student.type]
    }

    implicit val occupationReader = deriveReader[Occupation]
  }

  case class WorkingPerson(name: String, surname: String, occupation: Occupation)

  val res = ConfigSource.string("{ name: Isaac, surname: Newton, occupation.type: student }").load[WorkingPerson]

It works, but I need enum value like 'StudenT' and if I do so I got "ConvertFailure(UnexpectedValueForFieldCoproductHint(Unquoted("student"))"

1

There are 1 answers

3
Gastón Schabas On BEST ANSWER

If you want to change how the field is being read you need to provide a hint.

For sealed families, PureConfig provides a way to customize the conversion without replacing the default ConfigReader. By putting in scope an instance of CoproductHint for that sealed family, we can customize how the disambiguation is made. For example, if type clashes with one of the fields of a case class option, we can use another field.

import pureconfig.generic.FieldCoproductHint
implicit val animalConfHint = new FieldCoproductHint[AnimalConf]("kind")

FieldCoproductHint can also be adapted to write class names in a different way. First, define a new FieldCoproductHint in implicit scope:

implicit val animalConfHint = new FieldCoproductHint[AnimalConf]("type") {
  override def fieldValue(name: String) = name.dropRight("Conf".length)
}

In this case, adding FieldCoproductHint[Occupation] is what you need to do

implicit val occupationConfHint = new FieldCoproductHint[Occupation]("type") {
  override def fieldValue(name: String) = name
}

I created a working example in scastie


Do you really need to use the Semi-Automatic derivation? You can get the same result just using the automatic one.

Here is the working example in scatsie

  • build.sbt
libraryDependencies += "com.github.pureconfig" %% "pureconfig" % "0.14.0"
  • main.scala
import pureconfig._
import pureconfig.generic.FieldCoproductHint
import pureconfig.generic.auto._

sealed trait Occupation extends Product with Serializable

implicit val occupationConfHint = new FieldCoproductHint[Occupation]("type") {
  override def fieldValue(name: String) = name
}

object Occupation {
  case class Employed(job: String) extends Occupation
  case object Unemployed extends Occupation
  case object StudenT extends Occupation
}

case class WorkingPerson(name: String, surname: String, occupation: Occupation)

val res = ConfigSource.string("{ name: Isaac, surname: Newton, occupation.type: StudenT }").load[WorkingPerson]
println(res)