Skip to content

Instantly share code, notes, and snippets.

@github-louis-fruleux
Created March 31, 2023 14:10
Show Gist options
  • Save github-louis-fruleux/95a93e749446f991e26b962428de76a3 to your computer and use it in GitHub Desktop.
Save github-louis-fruleux/95a93e749446f991e26b962428de76a3 to your computer and use it in GitHub Desktop.
Jsoniter scala codec for NonEmptyList
import cats.data.NonEmptyList
import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._
object Main extends App {
import Sample._
implicit val nelSampleCodec: JsonValueCodec[NonEmptyList[Sample]] = Codecs.make
println(readFromArray[NonEmptyList[Sample]](
"""[
| {"id": 0},
| {"id": 1}
|]""".stripMargin
.getBytes("UTF-8"))
) // NonEmptyList(Sample(1), Sample(0)), note the reverse order
println(writeToString[NonEmptyList[Sample]](NonEmptyList.of(Sample(0), Sample(1)))) // [{"id":0},{"id":1}]
}
final case class Sample(id: Int)
object Sample {
implicit val codecSample: JsonValueCodec[Sample] =
JsonCodecMaker.make(CodecMakerConfig)
}
object Codecs {
implicit def make[A: JsonValueCodec](implicit codecA: JsonValueCodec[A]): JsonValueCodec[NonEmptyList[A]] =
new JsonValueCodec[NonEmptyList[A]] {
override def decodeValue(in: JsonReader, default: NonEmptyList[A]): NonEmptyList[A] = {
if (in.isNextToken('[')) {
val listA = decodeSeqInReverseOrder(in)(codecA)
if (in.isNextToken(']')) NonEmptyList.fromListUnsafe(listA)
else in.readNullOrTokenError(default, ']')
}
else in.readNullOrTokenError(default, '[')
}
override def encodeValue(x: NonEmptyList[A], out: JsonWriter): Unit = {
out.writeArrayStart()
codecA.encodeValue(x.head, out)
x.tail.foreach { elt =>
codecA.encodeValue(elt, out)
}
out.writeArrayEnd()
}
override def nullValue: NonEmptyList[A] = null
}
private def decodeSeqInReverseOrder[A](in: JsonReader)(implicit codecA: JsonValueCodec[A]): List[A] = {
var res = List.empty[A]
res ::= codecA.decodeValue(in, codecA.nullValue)
while (in.isNextToken(',')) {
res ::= codecA.decodeValue(in, codecA.nullValue)
}
in.rollbackToken()
res
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment