如何在kotlinx.serialization.json.JsonElement与jooq.JSON之间转换?
在kotlinx JsonElement与jOOQ JSON间无字符串序列化转换
当然可以实现。jOOQ的JSON(含JSONB)是JSON字符串的轻量包装,而kotlinx.serialization的JsonElement是内存JSON树结构。要避免显式的字符串序列化/反序列化步骤,可以用以下两种高效方案:
1. 基于CharSequence的直接转换
jOOQ的JSON类实现了CharSequence接口,而kotlinx.serialization的Json解析器支持直接解析CharSequence,无需先调用toString()生成中间字符串:
从jOOQ JSON转kotlinx JsonElement
import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import org.jooq.JSON fun JSON.toJsonElement(): JsonElement { // 直接传入JSON实例(CharSequence),跳过toString()的字符串拷贝 return Json.decodeFromString(this) }
从kotlinx JsonElement转jOOQ JSON
通过StringBuilder直接写入JSON内容,避免生成额外的字符串对象:
import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.encodeToWriter import org.jooq.JSON fun JsonElement.toJooqJson(): JSON { val sb = StringBuilder() Json.encodeToWriter(this, sb) // 用StringBuilder直接构建jOOQ JSON,减少内存开销 return JSON.json(sb) }
2. 自定义jOOQ数据绑定(ORM场景首选)
如果在jOOQ的ORM映射中直接用JsonElement作为实体字段类型,可自定义Binding实现无字符串序列化的数据库交互:
import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import org.jooq.* import org.jooq.impl.DSL import java.sql.SQLException import java.sql.Types class JsonElementBinding : Binding<JSON, JsonElement> { override fun converter(): Converter<JSON, JsonElement> { return object : Converter<JSON, JsonElement> { override fun from(dbJson: JSON?): JsonElement? { return dbJson?.let { Json.decodeFromString(it) } } override fun to(element: JsonElement?): JSON? { return element?.let { val sb = StringBuilder() Json.encodeToWriter(it, sb) JSON.json(sb) } } override fun fromType(): Class<JSON> = JSON::class.java override fun toType(): Class<JsonElement> = JsonElement::class.java } } override fun sql(ctx: BindingSQLContext<JsonElement>) { ctx.render().visit(DSL.val(ctx.convert(converter()).value())).sql("::json") } override fun register(ctx: BindingRegisterContext<JsonElement>) { ctx.statement().registerOutParameter(ctx.index(), Types.VARCHAR) } override fun set(ctx: BindingSetStatementContext<JsonElement>) { ctx.statement().setString(ctx.index(), ctx.convert(converter()).value()?.data()) } override fun set(ctx: BindingSetSQLOutputContext<JsonElement>) { throw SQLException("Not supported") } override fun get(ctx: BindingGetResultSetContext<JsonElement>) { ctx.convert(converter()).value(JSON.json(ctx.resultSet().getString(ctx.index()))) } override fun get(ctx: BindingGetStatementContext<JsonElement>) { ctx.convert(converter()).value(JSON.json(ctx.statement().getString(ctx.index()))) } override fun get(ctx: BindingGetSQLInputContext<JsonElement>) { throw SQLException("Not supported") } }
使用时在实体表定义中指定绑定:
import org.jooq.TableField import org.jooq.impl.TableImpl data class MyEntity( val id: Long, val data: JsonElement ) class MyEntityTable(name: String = "my_entity") : TableImpl<MyEntityRecord>(name) { val ID: TableField<MyEntityRecord, Long> = createField("id", SQLDataType.BIGINT.notNull()) val DATA: TableField<MyEntityRecord, JsonElement> = createField( "data", SQLDataType.JSON, this, "", JsonElementBinding() ) }
关键说明
这里的“无字符串序列化”指避免显式的中间字符串对象创建与拷贝(比如jsonElement.toString()再转jOOQ JSON)。jOOQ的JSON类本身基于字符串包装,底层仍依赖JSON字符串,但上述方案通过CharSequence兼容、StringBuilder直接写入等方式,大幅减少了不必要的内存开销。
内容的提问来源于stack exchange,提问作者Emre
相关产品推荐
相关产品推荐

