There are a ton of scala json libraries. But for all of them, there’s a significant amount of “getting in the way”. Arkane imports, different syntaxes, and so on. I’ve been doing some typescript hacking, and not that surprisingly, json just works in that world. The DOTY type system is able to represent just about everything that exists in typescript. So is there a good reason why we can’t have a light-weight, optionally typed extensible record system that “just works” and gives a zero boilerplate way to interface with things like json? I’m not suggesting we repeat the experiment of embedding json into the language like we did xml, but surely there’s some way we can come up with a generic data value expression syntax that can then be ‘read into’ case classes, json, xml, and the rest, by virtue of having the right implicit in scope?
The lightest weight solution I can think of is to have a ‘named tuples’ type that gives something that shadows the tuples-as-hlist structures but with a constant field for the property name. If that was bolted onto some macro/inline magic, then the data expressions could be rendered directly into the appropriate calls, without going via an intermediate representation.
val dataExpr = ( name = "Matthew", age = 43) // NamedTuple["name".type, String]::NamedTuple["age".type, Int]::NamedTupleNil case class NameAge(name: String, age: 43) val exprAsCaseClass: NameAge = ( name = "Matthew", age = 43) // CstrArg[String], CstrArg[Int] => NamedTuple[....] => NameAge val exprAsJson: Json = ( name = "Matthew", age = 43) // JsonProp[String], JsonProp[Int] => NamedTuple[...] => Json
The hope would be that wherever possible, code handling named tuple data would be seeing
someCallback(name: String, value: V) or
anotherCallback[Name, V](value: V), and that the expressions themselves would only exist as nested function calls, and ideally not even that if the callbacks were macros that generated tightly-coupled code.
For data without a compile-time-known schema, we’d need the property names to be first-class rather than hidden in the type system.
I know various things like this already exist, particularly in shapeless, but they all come with a lot of ceremony and not insignificant run-time cost. Particularly in setting up and tearing down the intermediate representation, but also in the syntax and the game of guess the imports.
I have the use for semi-structured data like this in many places, particularly anything that touches databases or statistics.