2

As an exercise and some in-house util i'm building, i'd like to convert a java properties file to json hierarchy

foo.bar=15
foo.lots.dir=/tmp/test
foo.baz.host=localhost
foo.baz.port=333

I've managed to converted to a scala map, here's the code:

import java.util._
import scala.io._
import scala.collection.JavaConverters._
import java.io._

val props : Properties = new Properties();

In a repl, you get

scala> props.asScala
res3: scala.collection.mutable.Map[String,String] = Map(foo.bar -> 15, foo.lots.dir -> /tmp/test, foo.baz.host -> localhost, foo.baz.port -> 333)

Question now becomes, how do I iterate this map and collapse the dot notation to a nested map:

 Map(
     foo -> Map(
         bar -> 15, 
         baz -> Map(
             port -> 333, 
             host -> localhost
         )
     )
 )

perhaps using a scala recursion? ;-)

This will feed into a JSON builder and convert it to JSON format. (Which the code i'll post here as edit, once i figure out how to do the above nested map)

4

2 回答 2

0

甚至不要尝试嵌套地图。问题是,您将与类型纠缠不清,试图区分对象、数组、叶节点等。您最终将创建自己的抽象语法树 (AST)。

只需遍历地图上的现有节点并直接创建 JSON AST。我非常喜欢 json4s 上的那个。此外,JSON 库中有很多方法可以让您的生活更轻松。

于 2015-11-02T19:34:21.237 回答
0

看起来不像描述的那么简单的任务:) 但是使用 scala + 功能方法 + 递归 - 可以实现。检查下一个代码。

 val map = Map("foo.bar" -> "15", "foo.lots.dir" -> "/tmp/test", "foo.baz.host" -> "localhost", "foo.baz.port" -> "333")


  def grouping(m: Map[List[String], Any]) : Map[List[String], Any] = {
    println(m)
    val rr = m.filter(_._1.nonEmpty).groupBy(_._1.head).map { el =>
      val internalMap = el._2.map(eel => eel._1.tail -> eel._2)
      internalMap.size match {
        case 1 => el._1 -> internalMap.head._2
        case other => el._1 -> grouping(internalMap)
      }
    }
    rr.map(el => List(el._1) -> el._2)
  }

  println(
    grouping(map.map(e => e._1.split("\\.").toList -> e._2))
  )

我的结果是:

Map(
    List(foo) -> Map(
        List(baz) -> Map(
            List(host) -> localhost, 
            List(port) -> 333
            ), 
        List(lots) -> /tmp/test, 
        List(bar) -> 15
    )
)

从科学的角度来看,实施起来很有趣。但老实说,我没有看到任何真正的应用。最好Tree在每个节点用case class(name, child or value).

于 2015-11-02T19:50:01.673 回答