Skip to content

Commit ea548ef

Browse files
Add implementation for JsonDecoder in DefaultBsonDecoder
Signed-off-by: Mark <mark.vogel@nomadgcs.com>
1 parent 467c509 commit ea548ef

File tree

1 file changed

+95
-1
lines changed

1 file changed

+95
-1
lines changed

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

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,28 @@ 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.json.Json
31+
import kotlinx.serialization.json.JsonArray
32+
import kotlinx.serialization.json.JsonDecoder
33+
import kotlinx.serialization.json.JsonElement
34+
import kotlinx.serialization.json.JsonNull
35+
import kotlinx.serialization.json.JsonObject
36+
import kotlinx.serialization.json.JsonPrimitive
37+
import kotlinx.serialization.json.buildJsonArray
38+
import kotlinx.serialization.json.buildJsonObject
3039
import kotlinx.serialization.modules.SerializersModule
3140
import org.bson.AbstractBsonReader
41+
import org.bson.BsonBinarySubType
3242
import org.bson.BsonInvalidOperationException
3343
import org.bson.BsonReader
3444
import org.bson.BsonType
3545
import org.bson.BsonValue
46+
import org.bson.UuidRepresentation
3647
import org.bson.codecs.BsonValueCodec
3748
import org.bson.codecs.DecoderContext
49+
import org.bson.internal.UuidHelper
3850
import org.bson.types.ObjectId
51+
import java.util.Base64
3952

4053
/**
4154
* The BsonDecoder interface
@@ -58,7 +71,14 @@ internal open class DefaultBsonDecoder(
5871
internal val reader: AbstractBsonReader,
5972
override val serializersModule: SerializersModule,
6073
internal val configuration: BsonConfiguration
61-
) : BsonDecoder, AbstractDecoder() {
74+
) : BsonDecoder, JsonDecoder, AbstractDecoder() {
75+
76+
override val json = Json {
77+
explicitNulls = configuration.explicitNulls
78+
encodeDefaults = configuration.encodeDefaults
79+
classDiscriminator = configuration.classDiscriminator
80+
serializersModule = this@DefaultBsonDecoder.serializersModule
81+
}
6282

6383
private data class ElementMetadata(val name: String, val nullable: Boolean, var processed: Boolean = false)
6484
private var elementsMetadata: Array<ElementMetadata>? = null
@@ -178,8 +198,82 @@ internal open class DefaultBsonDecoder(
178198

179199
override fun decodeObjectId(): ObjectId = readOrThrow({ reader.readObjectId() }, BsonType.OBJECT_ID)
180200
override fun decodeBsonValue(): BsonValue = bsonValueCodec.decode(reader, DecoderContext.builder().build())
201+
202+
override fun decodeJsonElement(): JsonElement = reader.run {
203+
204+
if (state == AbstractBsonReader.State.INITIAL ||
205+
state == AbstractBsonReader.State.SCOPE_DOCUMENT ||
206+
state == AbstractBsonReader.State.TYPE) {
207+
readBsonType()
208+
}
209+
210+
if (state == AbstractBsonReader.State.NAME) {
211+
// ignore name
212+
skipName()
213+
}
214+
// @formatter:off
215+
return when (currentBsonType) {
216+
BsonType.NULL -> { readNull(); JsonNull } // We have to read null
217+
BsonType.BOOLEAN -> JsonPrimitive(readBoolean())
218+
BsonType.INT32 -> JsonPrimitive(readInt32())
219+
BsonType.INT64 -> JsonPrimitive(readInt64())
220+
BsonType.DOUBLE -> JsonPrimitive(readDouble())
221+
BsonType.DECIMAL128 -> JsonPrimitive(readDecimal128())
222+
BsonType.STRING -> JsonPrimitive(readString())
223+
BsonType.DOCUMENT -> readJsonObject()
224+
BsonType.ARRAY -> readJsonArray()
225+
BsonType.OBJECT_ID -> JsonPrimitive(readObjectId().toHexString())
226+
BsonType.DATE_TIME -> JsonPrimitive(readDateTime())
227+
BsonType.TIMESTAMP -> JsonPrimitive(readTimestamp().value)
228+
BsonType.REGULAR_EXPRESSION -> JsonPrimitive(readRegularExpression().pattern)
229+
BsonType.BINARY -> {
230+
val subtype = peekBinarySubType()
231+
val data = readBinaryData().data
232+
when (subtype) {
233+
BsonBinarySubType.UUID_LEGACY.value ->
234+
JsonPrimitive(UuidHelper.decodeBinaryToUuid(data, subtype, UuidRepresentation.JAVA_LEGACY).toString())
235+
BsonBinarySubType.UUID_STANDARD.value ->
236+
JsonPrimitive(UuidHelper.decodeBinaryToUuid(data, subtype, UuidRepresentation.STANDARD).toString())
237+
else -> JsonPrimitive(Base64.getEncoder().encodeToString(data))
238+
}
239+
}
240+
else -> error("unsupported json type: $currentBsonType")
241+
}
242+
// @formatter:on
243+
}
244+
181245
override fun reader(): BsonReader = reader
182246

247+
private fun BsonReader.readJsonObject(): JsonObject {
248+
249+
readStartDocument()
250+
val obj = buildJsonObject {
251+
var type = readBsonType()
252+
while (type != BsonType.END_OF_DOCUMENT) {
253+
put(readName(), decodeJsonElement())
254+
type = readBsonType()
255+
}
256+
}
257+
258+
readEndDocument()
259+
return obj
260+
}
261+
262+
private fun BsonReader.readJsonArray(): JsonArray {
263+
264+
readStartArray()
265+
val array = buildJsonArray {
266+
var type = readBsonType()
267+
while (type != BsonType.END_OF_DOCUMENT) {
268+
add(decodeJsonElement())
269+
type = readBsonType()
270+
}
271+
}
272+
273+
readEndArray()
274+
return array
275+
}
276+
183277
private inline fun <T> readOrThrow(action: () -> T, bsonType: BsonType): T {
184278
return try {
185279
action()

0 commit comments

Comments
 (0)