Skip to content

Instantly share code, notes, and snippets.

@p-pavel
Created March 10, 2025 11:50
Show Gist options
  • Save p-pavel/7c03b45f97181c94bbefc07c879ed923 to your computer and use it in GitHub Desktop.
Save p-pavel/7c03b45f97181c94bbefc07c879ed923 to your computer and use it in GitHub Desktop.
Named tuples and json
import io.circe.*
import literal.*
import cats.implicits.*
import NamedTuple.NamedTuple
import language.experimental.namedTuples
@main
def greet =
type Person = (name: String, age: Int)
val greeting = json"""{"name": "Joe", "age": 42}"""
.as[Person]
.map(p => s"Hello, ${p.name}, you reached ${p.age}")
println(greeting)
// ------- Impl ------
class NamedTupleDecoder[Names <: Tuple, Values <: Tuple](data: Seq[(String, Decoder[?])])
extends Decoder[NamedTuple[Names, Values]]:
override def apply(c: HCursor): Decoder.Result[NamedTuple[Names, Values]] =
data
.map((name, decoder) => c.downField(name).as(using decoder))
.sequence
.map(vals => NamedTuple.build()(Tuple.fromArray(vals.toArray).asInstanceOf[Values]))
end NamedTupleDecoder
inline given decodeNamedTuple[Names <: Tuple, Vals <: Tuple]
: Decoder[NamedTuple.NamedTuple[Names, Vals]] =
val decoders = compiletime.summonAll[Tuple.Map[Vals, Decoder]]
val names = compiletime.constValueTuple[Names].toList.asInstanceOf[List[String]]
val untypedDecoders = decoders.toList.asInstanceOf[List[Decoder[?]]]
NamedTupleDecoder(names.zip(untypedDecoders))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment