Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created October 5, 2022 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arturaz/636dd5595c85d669781d9bc86c5813d8 to your computer and use it in GitHub Desktop.
Save arturaz/636dd5595c85d669781d9bc86c5813d8 to your computer and use it in GitHub Desktop.
Quill encoder/decoder with play-json
def jsEncoder[A](implicit w: Writes[A @@ SerializedInDB]): Encoder[A] = encoder[A](
java.sql.Types.OTHER,
(index: Index, value: A, row: PrepareRow) =>
row.setObject(index, writeJS(value), java.sql.Types.OTHER)
)
def jsOptEncoder[A](implicit w: Writes[A @@ SerializedInDB]): Encoder[Option[A]] = encoder[Option[A]](
java.sql.Types.OTHER,
(index: Index, maybeValue: Option[A], row: PrepareRow) => {
val json = maybeValue.fold2(null, a => writeJS(a)(w))
row.setObject(index, json, java.sql.Types.OTHER)
}
)
def jsDecoder[A](implicit r: Reads[A @@ SerializedInDB], ct: ClassTag[A @@ SerializedInDB]): Decoder[A] =
decoder[A] { row: ResultRow => index: Index =>
val pgObj = row.getObject(index).asInstanceOf[PGobject]
if (pgObj == null) throw new Exception(s"JSON is null for column $index in ${row.asString}")
parseJS(pgObj)
}
def jsOptDecoder[A](implicit r: Reads[A @@ SerializedInDB], ct: ClassTag[A @@ SerializedInDB]): Decoder[Option[A]] =
decoder[Option[A]] { row: ResultRow => index: Index =>
val pgObj = row.getObject(index).asInstanceOf[PGobject]
if (pgObj == null) None
else Some(parseJS(pgObj))
}
private[this] def writeJS[A](a: A)(implicit w: Writes[A @@ SerializedInDB]) =
Json.stringify(w.writes(SerializedInDB.tag(a)))
private[this] def parseJS[A](pgObj: PGobject)(implicit r: Reads[A], ct: ClassTag[A]): A = {
val jsString = pgObj.getValue
val js = Json.parse(jsString)
r.reads(js) match {
case JsSuccess(value, _) => value
case err: JsError => throw new Exception(
s"Can't parse JSON as ${ct.runtimeClass.getName}: ${JsError.toJson(err)}\n\nJson: $jsString"
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment