Hocon: чтение массива объектов из файла конфигурации - программирование
Подтвердить что ты не робот

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?

4b9b3361

Ответ 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)