web-dev-qa-db-ja.com

TypesafeConfigからのケースクラスのインスタンス化

(json4sまたは他のライブラリを使用して)jsonにシリアル化する機能を備えたscalaケースクラスがあるとします:

case class Weather(Zip : String, temp : Double, isRaining : Boolean)

[〜#〜] hocon [〜#〜] 設定ファイルを使用している場合:

allWeather {

   BeverlyHills {
    Zip : 90210
    temp : 75.0
    isRaining : false
  }

  Cambridge {
    Zip : 10013
    temp : 32.0
    isRainging : true
  }

}

typesafe config を使用してWeatherオブジェクトを自動的にインスタンス化する方法はありますか?

何か形のものを探しています

val config : Config = ConfigFactory.parseFile(new Java.io.File("weather.conf"))

val bevHills : Weather = config.getObject("allWeather.BeverlyHills").as[Weather]

このソリューションは、"allWeather.BeverlyHills"によって参照される値がjsonの「blob」であるという事実を活用できます。

私は明らかに自分のパーサーを書くことができました:

def configToWeather(config : Config) = 
  Weather(config.getString("Zip"), 
          config.getDouble("temp"), 
          config.getBoolean("isRaining"))

val bevHills = configToWeather(config.getConfig("allWeather.BeverlyHills"))

しかし、天気の定義を変更するにはconfigToWeatherも変更する必要があるため、これはエレガントではないようです。

よろしくお願いします。

typesafe構成ライブラリには インスタンス化するAPI Java Bean規則)を使用する構成からのオブジェクトがあります。しかし、私が理解しているように、ケースクラスはこれらのルールに従いません。

いくつかのscalaライブラリ タイプセーフな設定をラップし、あなたが探している特定の機能を提供するscala。

たとえば、 pureconfig を使用すると、configを読み取ると次のようになります。

val weather:Try[Weather] = loadConfig[Weather]

ここで、Weatherはconfig内の値のケースクラスです。

11
Nazarii Bardiuk

ナザリの答えを拡張すると、次のことが私のために働いた:

import scala.beans.BeanProperty

//The @BeanProperty and var are both necessary
case class Weather(@BeanProperty var Zip : String,
                   @BeanProperty var temp : Double,
                   @BeanProperty var isRaining : Boolean) {

  //needed by configfactory to conform to Java bean standard
  def this() = this("", 0.0, false)
}

import com.typesafe.config.ConfigFactory

val config = ConfigFactory.parseFile(new Java.io.File("allWeather.conf"))

import com.typesafe.config.ConfigBeanFactory

val bevHills = 
  ConfigBeanFactory.create(config.getConfig("allWeather.BeverlyHills"), classOf[Weather])

別のオプションは、以下のコードでcirce.configを使用することです。 https://github.com/circe/circe-config を参照してください

import io.circe.generic.auto._
import io.circe.config.syntax._

def configToWeather(conf: Config): Weather = {
  conf.as[Weather]("allWeather.BeverlyHills") match {
    case Right(c) => c
    case _ => throw new Exception("invalid configuration")
  }
}
0
esumitra