Построение динамического типа кортежа Scala из последовательности

#scala #types

#scala #типы

Вопрос:

Я пытаюсь сгенерировать некоторый json, используя библиотеку json4s, которая строит json с использованием dsl на основе вложенных структур кортежей. У меня есть scala Seq , который я хотел бы иметь возможность конвертировать во вложенность кортежей следующим образом:

 // scala Seq
val s = Seq("a", "b", "c", "d")
val rootItem = "id" -> 1234
// desired json
{
  "a" : {
    "b" : {
      "c" : {
        "d" : {
          "id" : 1234
        }
      }
    }
  }
}
 

Если я заставлю его игнорировать типы, я могу создать желаемую структуру кортежей следующим образом:

 // yields ("a", ("b", ("c", ("d", ("id", 1234)))))
s.foldRight[Any](rootItem)(_ -> _) 
 

но поскольку тип результата теперь обозначается как Any неявное преобразование, которое записывает это в json, не срабатывает (и генерирует исключение при явном вызове), несмотря на то, что фактический тип правильный. Я в недоумении, как построить эту структуру данных безопасным для типов способом. В идеале мне хотелось бы решение, способное соответствующим образом создать тип, хотя я понимаю, что это может быть невозможно, поскольку для этого требуется информация, доступная только во время выполнения (длина списка). Я знаю, что scala поддерживает рекурсивные типы, которые, по-видимому, потенциально подходят, но я не смог понять, как с ними работать в этом случае, и не знаю, безопасны ли они для «реальной» системы.

Ответ №1:

Вы не сможете сделать это с помощью простого старого сгиба, поскольку накопитель должен быть одного и того же типа все время.

Однако вы можете выполнить преобразование в JSON по ходу работы:

 val s = Seq("a", "b", "c", "d")
val rootItem = "id" -> 1234

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._

val json = s.foldRight[JObject](rootItem)(_ -> _)
 

И затем вы можете сделать следующее, поскольку json статически типизируется как JObject :

 scala> pretty(render(json))
res0: String = 
{
  "a" : {
    "b" : {
      "c" : {
        "d" : {
          "id" : 1234
        }
      }
    }
  }
}
 

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

Комментарии:

1. Прекрасно, это именно то, что я хотел, и намного проще, чем я боялся.