postgres jsonb 타입으로 컬럼을 정의하면 비정형데이터를 저장하는데 용이합니다. kotlin orm인 exposed로 해당 컬럼 타입을 정의할 일이 있어서.. 찾아봤는데요. jsonb 컬럼 타입은 exposed에서 기본적으로 제공하는 타입은 아니고, 아래와 같이 직접 overriding 해서 사용할 수 있습니다.
package com.sample.utils
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
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
class JsonbColumnType<T : Any>(
private val stringify: (T) -> String,
private val parse: (String) -> T
) : ColumnType() {
override fun sqlType() = JSONB
override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
super.setParameter(
stmt,
index,
value.let {
PGobject().apply {
this.type = sqlType()
this.value = value as String?
}
}
)
}
override fun valueFromDB(value: Any): Any {
return if (value is PGobject) {
value.value.let {
if (it != null) parse(it)
else value
}
} else value
}
override fun valueToString(value: Any?): String = when (value) {
is Iterable<*> -> nonNullValueToString(value)
else -> super.valueToString(value)
}
@Suppress("UNCHECKED_CAST")
override fun notNullValueToDB(value: Any) = stringify(value as T)
companion object {
const val JSONB = "JSONB"
}
}
fun <T : Any> Table.jsonb(name: String, stringify: (T) -> String, parse: (String) -> T): Column<T> =
registerColumn(name, JsonbColumnType(stringify, parse))
/**
* jsonb column with kotlinx.serialization as JSON serializer
*/
fun <T : Any> Table.jsonb(
name: String,
serializer: KSerializer<T>,
json: Json = Json {}
): Column<T> = jsonb(name, { json.encodeToString(serializer, it) }, { json.decodeFromString(serializer, it) })
이렇게 컬럼 타입을 새로 만들고 나서 아래처럼 설정해주면 됩니다. 추가로 json serializing 할때는 서버쪽에서 식별할 단계까지만 정의해주면 됩니다. 저는 상세 nest data 파싱은 프론트에서 했습니다.
package com.sample.data.rules
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.sample.utils.jsonb
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.dao.id.IntIdTable
@Serializable
data class LiveDetectRule(
val id: Int,
val active: String,
val ruletype: String,
val keyfield: String,
val confirms: String,
val conditions: List<Conditions>,
val ver: String,
val updatedat: String?
){
fun sepString(sep: String): String {
return "$id$sep$active$sep$ruletype$sep$keyfield$sep$confirms$sep$conditions$sep$ver\n"
}
}
object LiveDetectRuleTable : IntIdTable() {
val active = varchar("active", 255)
val ruletype = varchar("ruletype", 255)
val keyfield = varchar("keyfield", 255)
val corfirms = varchar("confirms", 255)
val conditions = jsonb("conditions", Conditions.serializer())
val ver = varchar("ver", 255)
val updatedat = varchar("updatedat", 255)
}
@Serializable
data class Conditions @JsonCreator constructor(
@JsonProperty("field") val field: String,
@JsonProperty("value") val value: String,
) {
override fun toString(): String {
return "{" +
"\"field\": \"$field\"," +
"\"value\": \"$value\"" +
"}"
}
}
'기타' 카테고리의 다른 글
파일 공유용 (0) | 2022.08.11 |
---|---|
[Linux] 파일 내용 일괄 변경하기 (0) | 2022.05.17 |
딥러닝 영상처리용 데이터셋 구하기 - Roboflow (0) | 2022.05.10 |
데이터 거버넌스란? (0) | 2022.05.09 |
Azure-204 교육 내용 정리 (0) | 2022.05.09 |