Typesafe config: How to iterate over configuration items

Viewed 14251

In my Play application I've a configuration like this:

social {
    twitter {
        url="https://twitter.com"
        logo="images/twitter.png"
    }
    facebook {
        url="https://www.facebook.com"
        logo="images/facebook.png"
    }
}

Ho do I iterate over all the social entries to get url and logo for each entry?

<table border="0" cellspacing="0" cellpadding="2"><tr>
    @configuration.getConfig("social").map { config =>
        @for(item <- config.entrySet) {
           <td><a href="item.getString("url")">
           <img src="@routes.Assets.at("item.getString("logo")").absoluteURL()" width="24" height="24"/></a></td>
        }
    }
</table>

Of course, item.getString in the snippet here above does not work... it just shows what I'm trying to achieve.

The final objective would be to be able to add any further social url without having to modify the page template.

7 Answers

Since collection.JavaConversions has since been deprecated in favor of collection.JavaConverters (and this question is the top result on a search for how to iterate through a Typesafe Config in Scala), I wanted to suggest a more modern version of Cole's great answer:

import collection.JavaConverters._

val socialConfig = ConfigFactory.load.getConfig("social")

for ( (name: String, configObject: ConfigObject) <- socialConfig.root.asScala) {
    println(name) // prints "twitter" or "facebook"

    val config = configObject.toConfig
    println(config.getString("url"))
    println(config.getString("logo"))
}

To be clear, socialConfig.root.asScala yields a standard Scala Map[String, ConfigObject] and you can iterate over it however you'd like.

import collection.JavaConversions._
val socialConfig = ConfigFactory.load.getConfig("social")

val socialConfigMap = socialConfig
  .root()
  .entrySet()
  .asScala
  .map(socialEntry => {
    println(socialEntry.getKey)
    val socialEntryConfig = socialEntry.getValue.asInstanceOf[ConfigObject].toConfig

    println(socialEntryConfig.getString("url"))
    println(socialEntryConfig.getString("logo"))
  })

For the config mentioned originally in question:

social {
  twitter {
    url="https://twitter.com"
    logo="images/twitter.png"
  }
  facebook {
    url="https://www.facebook.com"
    logo="images/facebook.png"
  }
}

A solution in Java is:

val socialConfig = ConfigFactory.load.getConfig("social");
ConfigList socials = socialConfig.getList("social");

Map<String, Object> map = socials.root().unwrapped();
for (Map.Entry<String, Object> cv : map.entrySet()) {
  Map<String, String> c = (Map<String, String>)cv.getValue();
  System.out.println(cv.getKey());
  System.out.println(c.getOrDefault("url", ""));
  System.out.println(c.getOrDefault("logo", ""));
}
Related