Skip to content

Instantly share code, notes, and snippets.

@dbousamra
Created November 19, 2015 00:02
Show Gist options
  • Select an option

  • Save dbousamra/62a07ce36a4bb643f672 to your computer and use it in GitHub Desktop.

Select an option

Save dbousamra/62a07ce36a4bb643f672 to your computer and use it in GitHub Desktop.
object DoobieHelpers {
/*
* See: https://tpolecat.github.io/doobie-0.2.0/10-Custom-Mappings.html
*
* Some modern databases support a json column type that can store structured data as a JSON document, along with
* various SQL extensions to allow querying and selecting arbitrary sub-structures. So an obvious thing we might
* want to do is provide a mapping from Scala model objects to JSON columns, via some kind of JSON serialization
* library.
*
* We can construct a Meta instance for the argonaut Json type by using the Meta.other constructor, which constructs
* a direct object mapping via JDBC's .getObject and .setObject. In the case of PostgreSQL the JSON values are
* marshalled via the PGObject type, which encapsulates an uninspiring (String, String) pair representing the schema
* type and its string value.
*/
implicit val JsonMeta: Meta[Json] =
Meta.other[PGobject]("json").nxmap[Json](
a => Parse.parse(a.getValue).leftMap[Json](sys.error).merge, // failure raises an exception
a => new PGobject <| (_.setType("json")) <| (_.setValue(a.nospaces))
)
/*
* Given this mapping to and from Json we can construct a further mapping to any type that has a CodecJson instance.
* The nxmap constrains us to reference types and requires a TypeTag for diagnostics, so the full type constraint
* is A >: Null : CodecJson: TypeTag. On failure we throw an exception; this indicates a logic or schema problem.
*/
def codecMeta[A >: Null : DecodeJson : EncodeJson : TypeTag]: Meta[A] = {
Meta[Json].nxmap[A](x => {
x.as[A].result.fold(p => {
sys.error(p._1)
}, identity)
},
_.asJson
)
}
/*
* Tells Doobie how to work with Joda Time instants.
*/
// implicit val JodaInstantMeta = codecMeta[Instant]
implicit val DateTimeMeta: Meta[Instant] =
Meta[java.sql.Timestamp].nxmap(
ts => new Instant(ts.getTime),
dt => new java.sql.Timestamp(dt.getMillis)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment