2015-11-02 83 views
1

作为练习和一些内部UTIL我建,我想采用Java属性文件转换成JSON层次转换Java属性映射到嵌套地图JSON

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

我已经成功地转换为Scala的地图,这里是代码:

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

val props : Properties = new Properties(); 

在REPL,你

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) 

问题现在变成了,我怎么遍历这个地图和折叠点符号嵌套地图:

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

也许使用Scala的递归? ;-)

这将馈入JSON构建器并将其转换为JSON格式。 (其中代码我将在这里发布为编辑,一旦我找出如何做上述嵌套地图)

回答

0

甚至不要尝试嵌套地图。事情是,你会得到巨大的类型纠结,试图区分对象,数组,叶节点等。你最终会创建自己的抽象语法树(AST)。

只需遍历地图上的现有节点并直接创建JSON AST即可。 I like the one on json4s a lot。另外,JSON库中有很多方法可以让您的生活更轻松。

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)来描述。