First I’d think that e.g.
JsValue shouldn’t require a huge amount of studying. Second, having a restricted set of types is a feature. With a
JsValue, there’s exactly 8 different forms it can take. A
Map[String, Any] can literally contain anything. I’ll have to guess which types are used to encode JSON arrays/numbers/…, I can’t rely on the compiler to tell me when I’ve forgotten to cover one of the cases, and so on.
I think you are conflating two things here. The
JsValue structure is completely equivalent to the
Map[String, Any] structure, and you could do the same check for array nesting depth in both. The convention of adding polymorphic subtype information as JSON attributes just makes this distinction easier, and it covers more ambiguous cases - imagine a list that can contain both absolute and relative coordinate pairs, both consisting of two numbers.
That’s the part you have completely omitted on the Clojure side. The equivalent of
json/read-str (slurp ...) with spray-json would simply be
JsonParser("/tmp/small-example.json"). That’s the format-level part, and the resulting structure is fully equivalent. Converting to the domain level (i.e.
Map[String,List[Perimeter]]) is the interesting part. (And I think I recall that I had given some suggestions at the time how this could be approached a bit more conveniently.)
And again, if you don’t like
JsObject and friends, a conversion to
Map[String, Any] should be feasible in a single, recursive pattern-matching function, if I’m not missing anything.