Преобразование свойств 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();

В ответ вы получаете

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 ответа

Это кажется не такой простой задачей, как описано:) Но используя 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),

Даже не пытайтесь использовать вложенную карту. Дело в том, что вы будете сильно запутываться с типами, пытаясь различить объекты, массивы, листовые узлы и т. Д. В итоге вы создадите свое собственное абстрактное синтаксическое дерево (AST).

Просто переберите существующие узлы на вашей карте и создайте JSON AST напрямую. Мне очень нравится тот, что на json4s. Кроме того, в библиотеках JSON есть множество методов, облегчающих вашу жизнь.

Другие вопросы по тегам