Skip to content

Commit 7e4661c

Browse files
rozzamarkvogelnomad
andcommitted
Added kotlinx.json JsonElement serialization support
JAVA-5239 --------- Co-authored-by: Mark <[email protected]>
1 parent 7d80cef commit 7e4661c

File tree

9 files changed

+518
-69
lines changed

9 files changed

+518
-69
lines changed

bson-kotlinx/build.gradle.kts

+8
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,27 @@ description = "Bson Kotlinx Codecs"
3838

3939
ext.set("pomName", "Bson Kotlinx")
4040

41+
java {
42+
registerFeature("jsonSupport") {
43+
usingSourceSet(sourceSets["main"])
44+
}
45+
}
46+
4147
dependencies {
4248
// Align versions of all Kotlin components
4349
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
4450
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
4551

4652
implementation(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.5.0"))
4753
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core")
54+
"jsonSupportImplementation"("org.jetbrains.kotlinx:kotlinx-serialization-json")
4855

4956
api(project(path = ":bson", configuration = "default"))
5057
implementation("org.jetbrains.kotlin:kotlin-reflect")
5158

5259
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
5360
testImplementation(project(path = ":driver-core", configuration = "default"))
61+
testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json")
5462
}
5563

5664
kotlin { explicitApi() }

bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/BsonDecoder.kt

+121-48
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import kotlinx.serialization.encoding.AbstractDecoder
2727
import kotlinx.serialization.encoding.CompositeDecoder
2828
import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE
2929
import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME
30+
import kotlinx.serialization.encoding.Decoder
3031
import kotlinx.serialization.modules.SerializersModule
3132
import org.bson.AbstractBsonReader
3233
import org.bson.BsonInvalidOperationException
@@ -36,6 +37,10 @@ import org.bson.BsonType
3637
import org.bson.BsonValue
3738
import org.bson.codecs.BsonValueCodec
3839
import org.bson.codecs.DecoderContext
40+
import org.bson.codecs.kotlinx.BsonDecoder.Companion.createBsonArrayDecoder
41+
import org.bson.codecs.kotlinx.BsonDecoder.Companion.createBsonDocumentDecoder
42+
import org.bson.codecs.kotlinx.BsonDecoder.Companion.createBsonMapDecoder
43+
import org.bson.codecs.kotlinx.BsonDecoder.Companion.createBsonPolymorphicDecoder
3944
import org.bson.internal.NumberCodecHelper
4045
import org.bson.internal.StringCodecHelper
4146
import org.bson.types.ObjectId
@@ -45,34 +50,93 @@ import org.bson.types.ObjectId
4550
*
4651
* For custom serialization handlers
4752
*/
48-
public sealed interface BsonDecoder {
53+
@ExperimentalSerializationApi
54+
internal sealed interface BsonDecoder : Decoder, CompositeDecoder {
55+
56+
/** Factory helper for creating concrete BsonDecoder implementations */
57+
companion object {
58+
59+
@Suppress("SwallowedException")
60+
private val hasJsonDecoder: Boolean by lazy {
61+
try {
62+
Class.forName("kotlinx.serialization.json.JsonDecoder")
63+
true
64+
} catch (e: ClassNotFoundException) {
65+
false
66+
}
67+
}
68+
69+
fun createBsonDecoder(
70+
reader: AbstractBsonReader,
71+
serializersModule: SerializersModule,
72+
configuration: BsonConfiguration
73+
): BsonDecoder {
74+
return if (hasJsonDecoder) JsonBsonDecoderImpl(reader, serializersModule, configuration)
75+
else BsonDecoderImpl(reader, serializersModule, configuration)
76+
}
77+
78+
fun createBsonArrayDecoder(
79+
descriptor: SerialDescriptor,
80+
reader: AbstractBsonReader,
81+
serializersModule: SerializersModule,
82+
configuration: BsonConfiguration
83+
): BsonArrayDecoder {
84+
return if (hasJsonDecoder) JsonBsonArrayDecoder(descriptor, reader, serializersModule, configuration)
85+
else BsonArrayDecoder(descriptor, reader, serializersModule, configuration)
86+
}
87+
88+
fun createBsonDocumentDecoder(
89+
descriptor: SerialDescriptor,
90+
reader: AbstractBsonReader,
91+
serializersModule: SerializersModule,
92+
configuration: BsonConfiguration
93+
): BsonDocumentDecoder {
94+
return if (hasJsonDecoder) JsonBsonDocumentDecoder(descriptor, reader, serializersModule, configuration)
95+
else BsonDocumentDecoder(descriptor, reader, serializersModule, configuration)
96+
}
97+
98+
fun createBsonPolymorphicDecoder(
99+
descriptor: SerialDescriptor,
100+
reader: AbstractBsonReader,
101+
serializersModule: SerializersModule,
102+
configuration: BsonConfiguration
103+
): BsonPolymorphicDecoder {
104+
return if (hasJsonDecoder) JsonBsonPolymorphicDecoder(descriptor, reader, serializersModule, configuration)
105+
else BsonPolymorphicDecoder(descriptor, reader, serializersModule, configuration)
106+
}
107+
108+
fun createBsonMapDecoder(
109+
descriptor: SerialDescriptor,
110+
reader: AbstractBsonReader,
111+
serializersModule: SerializersModule,
112+
configuration: BsonConfiguration
113+
): BsonMapDecoder {
114+
return if (hasJsonDecoder) JsonBsonMapDecoder(descriptor, reader, serializersModule, configuration)
115+
else BsonMapDecoder(descriptor, reader, serializersModule, configuration)
116+
}
117+
}
49118

50119
/** @return the decoded ObjectId */
51-
public fun decodeObjectId(): ObjectId
120+
fun decodeObjectId(): ObjectId
52121
/** @return the decoded BsonValue */
53-
public fun decodeBsonValue(): BsonValue
54-
55-
/** @return the BsonReader */
56-
public fun reader(): BsonReader
122+
fun decodeBsonValue(): BsonValue
57123
}
58124

59-
@ExperimentalSerializationApi
60-
internal open class DefaultBsonDecoder(
61-
internal val reader: AbstractBsonReader,
125+
@OptIn(ExperimentalSerializationApi::class)
126+
internal sealed class AbstractBsonDecoder(
127+
val reader: AbstractBsonReader,
62128
override val serializersModule: SerializersModule,
63-
internal val configuration: BsonConfiguration
129+
val configuration: BsonConfiguration
64130
) : BsonDecoder, AbstractDecoder() {
65131

66-
private data class ElementMetadata(val name: String, val nullable: Boolean, var processed: Boolean = false)
67-
private var elementsMetadata: Array<ElementMetadata>? = null
68-
private var currentIndex: Int = UNKNOWN_INDEX
69-
70132
companion object {
71-
val validKeyKinds = setOf(PrimitiveKind.STRING, PrimitiveKind.CHAR, SerialKind.ENUM)
133+
72134
val bsonValueCodec = BsonValueCodec()
73135
const val UNKNOWN_INDEX = -10
136+
val validKeyKinds = setOf(PrimitiveKind.STRING, PrimitiveKind.CHAR, SerialKind.ENUM)
137+
74138
fun validateCurrentBsonType(
75-
reader: AbstractBsonReader,
139+
reader: BsonReader,
76140
expectedType: BsonType,
77141
descriptor: SerialDescriptor,
78142
actualType: (descriptor: SerialDescriptor) -> String = { it.kind.toString() }
@@ -87,6 +151,10 @@ internal open class DefaultBsonDecoder(
87151
}
88152
}
89153

154+
private data class ElementMetadata(val name: String, val nullable: Boolean, var processed: Boolean = false)
155+
private var elementsMetadata: Array<ElementMetadata>? = null
156+
private var currentIndex: Int = UNKNOWN_INDEX
157+
90158
private fun initElementMetadata(descriptor: SerialDescriptor) {
91159
if (this.elementsMetadata != null) return
92160
val elementsMetadata =
@@ -134,14 +202,13 @@ internal open class DefaultBsonDecoder(
134202
?: UNKNOWN_NAME
135203
}
136204

137-
@Suppress("ReturnCount")
138205
override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {
139206
return when (descriptor.kind) {
140-
is StructureKind.LIST -> BsonArrayDecoder(descriptor, reader, serializersModule, configuration)
141-
is PolymorphicKind -> PolymorphicDecoder(descriptor, reader, serializersModule, configuration)
207+
is PolymorphicKind -> createBsonPolymorphicDecoder(descriptor, reader, serializersModule, configuration)
208+
is StructureKind.LIST -> createBsonArrayDecoder(descriptor, reader, serializersModule, configuration)
142209
is StructureKind.CLASS,
143-
StructureKind.OBJECT -> BsonDocumentDecoder(descriptor, reader, serializersModule, configuration)
144-
is StructureKind.MAP -> MapDecoder(descriptor, reader, serializersModule, configuration)
210+
StructureKind.OBJECT -> createBsonDocumentDecoder(descriptor, reader, serializersModule, configuration)
211+
is StructureKind.MAP -> createBsonMapDecoder(descriptor, reader, serializersModule, configuration)
145212
else -> throw SerializationException("Primitives are not supported at top-level")
146213
}
147214
}
@@ -152,18 +219,15 @@ internal open class DefaultBsonDecoder(
152219
is StructureKind.MAP,
153220
StructureKind.CLASS,
154221
StructureKind.OBJECT -> reader.readEndDocument()
155-
else -> super.endStructure(descriptor)
222+
else -> {}
156223
}
157224
}
158225

159226
override fun decodeByte(): Byte = NumberCodecHelper.decodeByte(reader)
160-
161227
override fun decodeChar(): Char = StringCodecHelper.decodeChar(reader)
162228
override fun decodeFloat(): Float = NumberCodecHelper.decodeFloat(reader)
163-
164229
override fun decodeShort(): Short = NumberCodecHelper.decodeShort(reader)
165230
override fun decodeBoolean(): Boolean = reader.readBoolean()
166-
167231
override fun decodeDouble(): Double = NumberCodecHelper.decodeDouble(reader)
168232
override fun decodeInt(): Int = NumberCodecHelper.decodeInt(reader)
169233
override fun decodeLong(): Long = NumberCodecHelper.decodeLong(reader)
@@ -183,7 +247,6 @@ internal open class DefaultBsonDecoder(
183247

184248
override fun decodeObjectId(): ObjectId = readOrThrow({ reader.readObjectId() }, BsonType.OBJECT_ID)
185249
override fun decodeBsonValue(): BsonValue = bsonValueCodec.decode(reader, DecoderContext.builder().build())
186-
override fun reader(): BsonReader = reader
187250

188251
private inline fun <T> readOrThrow(action: () -> T, bsonType: BsonType): T {
189252
return try {
@@ -197,13 +260,20 @@ internal open class DefaultBsonDecoder(
197260
}
198261
}
199262

200-
@OptIn(ExperimentalSerializationApi::class)
201-
private class BsonArrayDecoder(
263+
/** The default Bson Decoder implementation */
264+
internal open class BsonDecoderImpl(
265+
reader: AbstractBsonReader,
266+
serializersModule: SerializersModule,
267+
configuration: BsonConfiguration
268+
) : AbstractBsonDecoder(reader, serializersModule, configuration)
269+
270+
/** The Bson array decoder */
271+
internal open class BsonArrayDecoder(
202272
descriptor: SerialDescriptor,
203273
reader: AbstractBsonReader,
204274
serializersModule: SerializersModule,
205275
configuration: BsonConfiguration
206-
) : DefaultBsonDecoder(reader, serializersModule, configuration) {
276+
) : AbstractBsonDecoder(reader, serializersModule, configuration) {
207277

208278
init {
209279
validateCurrentBsonType(reader, BsonType.ARRAY, descriptor)
@@ -218,13 +288,29 @@ private class BsonArrayDecoder(
218288
}
219289
}
220290

291+
/** The Bson document decoder */
221292
@OptIn(ExperimentalSerializationApi::class)
222-
private class PolymorphicDecoder(
293+
internal open class BsonDocumentDecoder(
223294
descriptor: SerialDescriptor,
224295
reader: AbstractBsonReader,
225296
serializersModule: SerializersModule,
226297
configuration: BsonConfiguration
227-
) : DefaultBsonDecoder(reader, serializersModule, configuration) {
298+
) : AbstractBsonDecoder(reader, serializersModule, configuration) {
299+
300+
init {
301+
validateCurrentBsonType(reader, BsonType.DOCUMENT, descriptor) { it.serialName }
302+
reader.readStartDocument()
303+
}
304+
}
305+
306+
/** The Bson polymorphic class decoder */
307+
@OptIn(ExperimentalSerializationApi::class)
308+
internal open class BsonPolymorphicDecoder(
309+
descriptor: SerialDescriptor,
310+
reader: AbstractBsonReader,
311+
serializersModule: SerializersModule,
312+
configuration: BsonConfiguration
313+
) : AbstractBsonDecoder(reader, serializersModule, configuration) {
228314
private var index = 0
229315
private var mark: BsonReaderMark?
230316

@@ -239,7 +325,7 @@ private class PolymorphicDecoder(
239325
it.reset()
240326
mark = null
241327
}
242-
return deserializer.deserialize(DefaultBsonDecoder(reader, serializersModule, configuration))
328+
return deserializer.deserialize(BsonDecoder.createBsonDecoder(reader, serializersModule, configuration))
243329
}
244330

245331
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
@@ -266,27 +352,14 @@ private class PolymorphicDecoder(
266352
}
267353
}
268354

355+
/** The Bson map decoder */
269356
@OptIn(ExperimentalSerializationApi::class)
270-
private class BsonDocumentDecoder(
271-
descriptor: SerialDescriptor,
272-
reader: AbstractBsonReader,
273-
serializersModule: SerializersModule,
274-
configuration: BsonConfiguration
275-
) : DefaultBsonDecoder(reader, serializersModule, configuration) {
276-
init {
277-
validateCurrentBsonType(reader, BsonType.DOCUMENT, descriptor) { it.serialName }
278-
reader.readStartDocument()
279-
}
280-
}
281-
282-
@OptIn(ExperimentalSerializationApi::class)
283-
private class MapDecoder(
357+
internal open class BsonMapDecoder(
284358
descriptor: SerialDescriptor,
285359
reader: AbstractBsonReader,
286360
serializersModule: SerializersModule,
287361
configuration: BsonConfiguration
288-
) : DefaultBsonDecoder(reader, serializersModule, configuration) {
289-
362+
) : AbstractBsonDecoder(reader, serializersModule, configuration) {
290363
private var index = 0
291364
private var isKey = false
292365

0 commit comments

Comments
 (0)