3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ScalaAdvent Calendar 2018

Day 5

scalaでconfig読むときに便利そうなライブラリ

Posted at

typesafe configを便利に使うためのライブラリを2つ紹介してみます。

PureConfig

A boilerplate-free library for loading configuration files

amm使います。

$ amm
Loading...
Welcome to the Ammonite Repl 1.4.4
(Scala 2.12.7 Java 1.8.0_144)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi

pureconfigを読み込みます。

@ import $ivy.`com.github.pureconfig::pureconfig:0.10.1`
import $ivy.$

@ import pureconfig.generic.auto._
import pureconfig.generic.auto._

@ import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigFactory

型定義します。

@ {
  case class RedisConf(host: String, port: Int)
  case class MySQLConf(host: String, port: Int)
  case class Conf(mySQLConf: MySQLConf, redisClusterConf: Set[RedisConf])
  }

今回はreplなのでapplication.confを置くのではなく、文字列でconfを定義します。

@ val conf = ConfigFactory.parseString("""{ my-sql-conf: { host: "my1", port: 3306 }, redis-cluster-conf: [ { host: "re1", port: 7000 } ] }""")

loadConfigするとEitherで結果がかえってきます。

@ pureconfig.loadConfig[Conf](conf)
res5: Either[pureconfig.error.ConfigReaderFailures, Conf] = Right(Conf(MySQLConf("my1", 3306), Set(RedisConf("re1", 7000))))

便利ですね!

デフォルトだとキーはkebabCaseですが、hintをcamelCaseにしてあげるとcamelでもかけます。

@ import pureconfig._
import pureconfig._

@ implicit def hint[T] = ProductHint[T](ConfigFieldMapping(CamelCase, CamelCase))

@ pureconfig.loadConfig[Conf](conf)
res10: Either[error.ConfigReaderFailures, Conf] = Left(ConfigReaderFailures(ConvertFailure(KeyNotFound("mySQLConf", Set("my-sql-conf")), None, ""), List(ConvertFailure(KeyNotFound("redisClusterConf", Set("redis-cluster-conf")), None, ""))))

sealed traitも対応していて、その中でもenumも対応してました。

@ {
  import pureconfig.generic.EnumCoproductHint

  sealed trait Season
  case object Spring extends Season
  case object Summer extends Season
  case object Autumn extends Season
  case object Winter extends Season

  implicit val seasonHint = new EnumCoproductHint[Season]

  case class MyConf(list: List[Season])
  }
@ loadConfig[MyConf](ConfigFactory.parseString("{ list: [spring, summer, autumn, winter] }"))
res12: Either[error.ConfigReaderFailures, MyConf] = Right(MyConf(List(Spring, Summer, Autumn, Winter)))

便利ですね!

他にもcase classのデフォルト値を使うことができたりするみたいです。

shapelessで型クラスをderiveしてるみたいです。多機能でcatsとか他のライブラリとの親和性も別モジュールで提供してるよう。

ficus

Scala-friendly companion to Typesafe config

まずライブラリを読み込みます。

@ import $ivy.`com.iheart::ficus:1.4.3`

@ import net.ceedubs.ficus.Ficus._

さっき同じやつ使います。

@ {
  case class RedisConf(host: String, port: Int)
  case class MySQLConf(host: String, port: Int)
  case class Conf(mySQLConf: MySQLConf, redisClusterConf: Set[RedisConf])
  }

@ import net.ceedubs.ficus.readers.ArbitraryTypeReader._

@ val conf = ConfigFactory.parseString("""{ mySQLConf: { host: "my1", port: 3306 }, redisClusterConf: [ { host: "re1", port: 7000 } ] }""")

@ conf.as[Conf](".")
res11: Conf = Conf(MySQLConf("my1", 3306), Set(RedisConf("re1", 7000)))

こっちのライブラリはmacroで取ってきてるみたいです。
軽量だし実用的にはこっちで十分そう。

おわり

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?