Skip to content
Draft

wip #110

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.ks3.standard

import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.serializer

/**
* Creates a serializer that will parse a JSON property into a [T] element, or `null` if the element fails to parse.
*/
inline fun <reified T> lenientJsonPropertyDeserializer(explicitElementSerializer: KSerializer<T>? = null) =
object : KSerializer<T?> {
private val elementSerializer = explicitElementSerializer ?: serializer<T>()
override val descriptor: SerialDescriptor = elementSerializer.descriptor

override fun deserialize(decoder: Decoder): T? {
require(decoder is JsonDecoder) { "This deserializer can only be used with Json" }
val json = decoder.json
val item = decoder.decodeJsonElement()
return try {
json.decodeFromJsonElement(elementSerializer, item)
} catch (e: SerializationException) {
null
} catch (e: IllegalArgumentException) {
null
}
}

override fun serialize(
encoder: Encoder,
value: T?,
): Unit = error("Can only be used for deserialization")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.ks3.standard

import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

private object LenientIntParser : KSerializer<Int?> by lenientJsonPropertyDeserializer()

private typealias LenientInt =
@Serializable(with = LenientIntParser::class)
Int?

class LenientJsonPropertySerializerTest : StringSpec(
{
@Serializable
data class Foo(
val bar: String,
val baz: LenientInt,
)

"Invalid value is discarded" {
Json.decodeFromString<Foo>("""{"bar": "bar", "baz": "x"}""") shouldBe Foo("bar", null)
}
},
)