7
votes

Let say I have a config file with the following:

someConfig: [
{"t1" :
  [ {"t11" : "v11",
     "t12" : "v12",
     "t13" : "v13",
     "t14" : "v14",
     "t15" : "v15"},

   {"t21" : "v21",
     "t22" : "v22",
     "t23" : "v13",
     "t24" : "v14",
     "t25" : "v15"}]
  },
 "p1" :
  [ {"p11" : "k11",
     "p12" : "k12",
     "p13" : "k13",
     "p14" : "k14",
     "p15" : "k15"},

   {"p21" : "k21",
     "p22" : "k22",
     "p23" : "k13",
     "p24" : "k14",
     "p25" : "k15"}]
  }
]

I would like to retrieve it as a Scala immutable collection Map[List[Map[String, String]]].

using the following code I am only able to retrieve it as a List of HashMaps (more precisely a $colon$colon of HashMap) which fails when I try to iterate trough it. Ideally to complete my code I need a way to convert the HashMap to scala maps

def example: Map[String, List[Map[String,String]]] = {
    val tmp = ConfigFactory.load("filename.conf")
    val mylist : Iterable[ConfigObject] = tmp.getObjectList("someConfig")
        .asScala
    (for {
            item : ConfigObject <- mylist
            myEntry: Entry[String, ConfigValue] <- item.entrySet().asScala
            name = entry.getKey
            value = entry.getValue.unwrapped()
            .asInstanceOf[util.ArrayList[Map[String,String]]]
            .asScala.toList
        } yield (name, value)).toMap
}
2

2 Answers

7
votes

This code should be able to give you what you are looking for.

It builds up lists and maps for your bespoke structure.

The final reduceLeft, is because your json starts with a list, someConfig: [ ], and so I've flattened that out. If you wanted you could probably have removed the [ ]'s, as they as probably not required to represent the data you have.

//These methods convert from Java lists/maps to Scala ones, so its easier to use
private def toMap(hashMap: AnyRef): Map[String, AnyRef] = hashMap.asInstanceOf[java.util.Map[String, AnyRef]].asScala.toMap
private def toList(list: AnyRef): List[AnyRef] = list.asInstanceOf[java.util.List[AnyRef]].asScala.toList

val someConfig: Map[String, List[Map[String, String]]] =
  config.getList("someConfig").unwrapped().map { someConfigItem =>
    toMap(someConfigItem) map {
      case (key, value) =>
        key -> toList(value).map {
          x => toMap(x).map { case (k, v) => k -> v.toString }
        }
    }
  }.reduceLeft(_ ++ _)
1
votes

if you stroe your configs in the application.conf like this

someConfig{
    list1{
        value1 = "myvalue1"
        value2 = "myvalue2"
        .....
        valueN = "myvalueN"
    }
    list2{
        ......
    }
    .....
    listN{
         ......
    }
}

you can do the following:

val myconfig = ConfigFactory.load().getObject("someConfig.list1").toConfig

and after you can acces the values like

myconfig.getString("value1")
myconfig.getString("value2")

etc.

which will return the strings "myvalue1", "myvalue2"

not the most elegant way but plain easy