Hocon: чтение массива объектов из файла конфигурации
Я создал приложение Play (2.1), которое использует конфигурацию в conf/application.conf
в формате Hocon.
Я хочу добавить в конфигурацию массив проектов. Файл conf/application.conf
выглядит следующим образом:
...
projects = [
{name: "SO", url: "http://stackoverflow.com/"},
{name: "google", url: "http://google.com"}
]
Я пытаюсь прочитать эту конфигурацию в проекте Scala:
import scala.collection.JavaConversions._
case class Project(name: String, url: String)
val projectList: List[Project] =
Play.maybeApplication.map{x =>
val simpleConfig = x.configration.getObjectList("projects").map{y =>
y.toList.map{z =>
Project(z.get("name").toString, z.get("url").toString) // ?!? doesn't work
...
}}}}}}}} // *arg*
Этот подход кажется очень сложным, я теряюсь во многих Options
, и моя Eclipse IDE не может дать мне никаких подсказок о классах.
Есть ли у кого-нибудь пример того, как вы можете прочитать массив объектов из файла конфигурации Hocon?
Или я должен использовать для этого JSON файл с JSON-синтаксическим анализатором вместо Hocon?
Ответы
Ответ 1
В Play 2.1.2 работает следующее (у меня нет .maybeApplication
на моем play.Play
объекте, и я не уверен, почему вы это делаете):
import play.Play
import scala.collection.JavaConversions._
case class Project(name: String, url: String)
val projectList: List[Project] = {
val projs = Play.application.configuration.getConfigList("projects") map { p =>
Project(p.getString("name"), p.getString("url")) }
projs.toList
}
println(projectList)
Выход:
List(Project(SO,http://stackoverflow.com/), Project(google,http://google.com))
Здесь не так много, хотя я не теряюсь во множестве экземпляров Option
(опять же, отличается от API, который у вас есть).
Что еще более важно, getConfigList
кажется более близким к тому, что вы хотите сделать, поскольку он возвращает List[play.Configuration]
, который позволяет вам указывать типы при поиске, а не прибегать к приведениям или вызовам .toString()
.
Ответ 2
Что вы пытаетесь выполнить с помощью этой части y.toList.map{z =>
? Если вы хотите получить коллекцию Project
в результате, почему бы просто не сделать:
val simpleConfig = x.configration.getObjectList("projects").map{y =>
Project(y.get("name").toString, y.get("url").toString)
}
В этом случае операция map
должна принимать экземпляры ConfigObject
, что и есть y
. Кажется, все, что вам нужно, чтобы получить ваши экземпляры Project
, поэтому я не уверен, почему вы toList
ing, что ConfigObject
(который является map
) в список Tuple2
, а затем дальше отображение этого снова.
Ответ 3
Учитывая, что содержимое массива Json и у вас есть класс case, вы можете попробовать использовать Json Play API и работать с объекты таким образом. Часть Inception должна сделать ее тривиальной.
Ответ 4
Если нормальная конфигурация HOCON, похожая на странные, ответит на это, будет работать
import javax.inject._
import play.api.Configuration
trait Barfoo {
def configuration: Configuration
def projects = for {
projectsFound <- configuration.getConfigList("projects").toList
projectConfig <- projectsFound
name <- projectConfig.getString("name").toList
url <- projectConfig.getString("url").toList
} yield Project(name,url)
}
class Foobar @Inject() (val configuration: Configuration) extends Barfoo
(Использование Play 2.4+ Injection)