转换Java属性以映射到嵌套映射到JSON

时间:2015-11-02 17:44:35

标签: json scala dictionary properties nested-map

作为练习和一些内部工具的构建,我想将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格式。 (一旦我弄清楚如何做上面的嵌套地图,我将在这里发布代码编辑)

2 个答案:

答案 0 :(得分:0)

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

只需迭代地图上的现有节点并直接创建JSON AST。 I like the one on json4s a lot。此外,JSON库中有很多方法可供您轻松使用。

答案 1 :(得分: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)