bodiam
05/24/2024, 7:25 AMvalue
attribute. The value attribute is sometimes a String, sometimes sometimes a Map/Object:
{
"claims": [
{
"name": "txn",
"type": "new",
"scope": "profile"
},
{
"name": "name",
"value": "Title Given Family",
"type": "new",
"scope": "profile"
},
{
"name": "address",
"value": {
"country": "Some Country",
"locality": "City",
"postal_code": "1000",
"region": "Region",
"street_address": "Street Address"
},
"type": "new",
"scope": "profile"
}
]
}
I've tried creating a custom KSerializer for the property, something like:
@Serializable
data class Claim(
val name: String,
val type: String,
val scope: String,
@Serializable(with = ClaimValueSerializer::class)
val value: Any?
)
But no luck so far, I'm getting JSON parsing issues, and I have a hard time to map both a map and string to the claim value. Can anyone give me a pointer on how to approach this?Vampire
05/24/2024, 7:45 AMbodiam
05/24/2024, 7:50 AMobject ClaimValueSerializer : KSerializer<Any> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("value", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Any) = TODO()
override fun deserialize(decoder: Decoder): Any {
val jsonElement = (decoder as? JsonDecoder)
?.decodeJsonElement()
?: throw IllegalStateException("This class can be loaded only by JSON")
return when (jsonElement) {
is JsonPrimitive -> jsonElement.content
is JsonObject -> jsonElement.toMap()
else -> throw IllegalArgumentException("Unsupported type")
}
}
}
And it actually works. I'm not sure if this is the "right" way of doing it, but happy to go forward with this.Adam S
05/24/2024, 7:50 AMvalue
to a JsonElement, and then manually decode it later on in the code
@Serializable
data class Claim(
// ...
val value: JsonElement? = null
)
bodiam
05/24/2024, 7:51 AMAdam S
05/24/2024, 7:52 AM"value": null
, so it'd be important to have a default valueAdam S
05/24/2024, 7:54 AMbodiam
05/24/2024, 7:56 AMI see in the first element in your example there's noah yes, that's a real example actually, I left it in to demonstrate the nullability of this attribute., so it'd be important to have a default value"value": null
Adam S
05/24/2024, 7:57 AMAdam S
05/24/2024, 7:57 AMbodiam
05/24/2024, 8:02 AMemail: String?
being not optional? Or does the above only apply to the default Serializable properties? (in my json, the value is missing, but even without a default value, it works fine, but this could be caused by my Custom serializer...)Adam S
05/24/2024, 8:05 AMAdam S
05/24/2024, 8:06 AMemail
has no default value it's required)
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@Serializable
data class ContactDetails(
val name: String,
val email: String?,
val active: Boolean = true,
val phoneNumber: String? = null,
)
fun main() {
val cd = Json.decodeFromString(ContactDetails.serializer(), """
{
"name": "x"
}
""".trimIndent())
println(cd)
}
Exception in thread "main" kotlinx.serialization.MissingFieldException: Field 'email' is required for type with serial name 'ContactDetails', but it was missing at path: $
bodiam
05/26/2024, 3:10 AMAdam S
05/26/2024, 7:52 AM