Skip to content

Instantly share code, notes, and snippets.

@nhalase
Created October 5, 2022 20:46
Show Gist options
  • Save nhalase/244a89dadf1b57c33c3c2179c3a46d85 to your computer and use it in GitHub Desktop.
Save nhalase/244a89dadf1b57c33c3c2179c3a46d85 to your computer and use it in GitHub Desktop.
JSONB support (PostgreSQL)
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.ColumnType
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
import org.postgresql.util.PGobject
inline fun <reified T : Any> Table.jsonb(
name: String,
kSerializer: KSerializer<T> = serializer(),
json: Json
): Column<T> = this.jsonb(
name = name,
stringify = { json.encodeToString(kSerializer, it) },
parse = { json.decodeFromString(kSerializer, it) }
)
fun <T : Any> Table.jsonb(name: String, stringify: (T) -> String, parse: (String) -> T): Column<T> =
registerColumn(name, JsonbColumnType(stringify, parse))
class JsonbColumnType<T : Any>(private val stringify: (T) -> String, private val parse: (String) -> T) : ColumnType() {
override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
val obj = PGobject()
obj.type = "jsonb"
if (value != null) {
obj.value = value as String
}
stmt[index] = obj
}
override fun sqlType(): String = "jsonb"
override fun valueFromDB(value: Any): Any {
return when (value) {
is PGobject -> parse(value.value ?: "")
is Map<*, *> -> value
is List<*> -> value
is Set<*> -> value
is Array<*> -> value
else -> {
println("unhandled value type: ${value::class}")
value
}
}
}
@Suppress("UNCHECKED_CAST")
override fun notNullValueToDB(value: Any) = stringify(value as T)
override fun valueToString(value: Any?): String = when (value) {
is Iterable<*> -> notNullValueToDB(value)
else -> super.valueToString(value)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment