Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a Map of lists of map from type safe config in scala

Tags:

scala

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
}
like image 227
issykazz Avatar asked Jul 24 '16 15:07

issykazz


2 Answers

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(_ ++ _)
like image 173
Bruce Lowe Avatar answered Sep 20 '22 17:09

Bruce Lowe


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

like image 32
Miklós Takács Avatar answered Sep 20 '22 17:09

Miklós Takács