-
Notifications
You must be signed in to change notification settings - Fork 181
Improve error message on JsonObject deserialization #426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
fdd40b3
5900d09
29a925c
fed6589
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ import kotlinx.serialization.encoding.Decoder | |
| import kotlinx.serialization.encoding.Encoder | ||
| import kotlinx.serialization.json.JsonContentPolymorphicSerializer | ||
| import kotlinx.serialization.json.JsonElement | ||
| import kotlinx.serialization.json.JsonObject | ||
| import kotlinx.serialization.json.JsonPrimitive | ||
| import kotlinx.serialization.json.jsonObject | ||
| import kotlinx.serialization.json.jsonPrimitive | ||
|
|
@@ -40,6 +41,15 @@ private fun JsonElement.getTypeOrNull(): String? = jsonObject["type"]?.jsonPrimi | |
| */ | ||
| private fun JsonElement.getType(): String = requireNotNull(getTypeOrNull()) { "Missing required 'type' field" } | ||
|
|
||
| @Throws(SerializationException::class) | ||
| private fun JsonElement.asJsonObject(): JsonObject { | ||
| if (this !is JsonObject) { | ||
| throw SerializationException("Invalid response. JsonObject expected, got: ${this::class.simpleName}") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What’s the benefit of this function for us?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only a better error message. |
||
| } | ||
| val jsonObject = this.jsonObject | ||
| return jsonObject | ||
| } | ||
|
|
||
| // ============================================================================ | ||
| // Method Serializer | ||
| // ============================================================================ | ||
|
|
@@ -131,7 +141,7 @@ internal object MediaContentPolymorphicSerializer : | |
| internal object ResourceContentsPolymorphicSerializer : | ||
| JsonContentPolymorphicSerializer<ResourceContents>(ResourceContents::class) { | ||
| override fun selectDeserializer(element: JsonElement): DeserializationStrategy<ResourceContents> { | ||
| val jsonObject = element.jsonObject | ||
| val jsonObject = element.asJsonObject() | ||
| return when { | ||
| "text" in jsonObject -> TextResourceContents.serializer() | ||
| "blob" in jsonObject -> BlobResourceContents.serializer() | ||
|
|
@@ -284,7 +294,7 @@ internal object ServerNotificationPolymorphicSerializer : | |
| * Returns EmptyResult serializer if the JSON object is empty or contains only metadata. | ||
| */ | ||
| private fun selectEmptyResult(element: JsonElement): DeserializationStrategy<EmptyResult>? { | ||
| val jsonObject = element.jsonObject | ||
| val jsonObject = element.asJsonObject() | ||
| return when { | ||
| jsonObject.isEmpty() || (jsonObject.size == 1 && "_meta" in jsonObject) -> EmptyResult.serializer() | ||
| else -> null | ||
|
|
@@ -296,7 +306,7 @@ private fun selectEmptyResult(element: JsonElement): DeserializationStrategy<Emp | |
| * Returns null if the structure doesn't match any known client result type. | ||
| */ | ||
| private fun selectClientResultDeserializer(element: JsonElement): DeserializationStrategy<ClientResult>? { | ||
| val jsonObject = element.jsonObject | ||
| val jsonObject = element.asJsonObject() | ||
| return when { | ||
| "model" in jsonObject && "role" in jsonObject -> CreateMessageResult.serializer() | ||
| "roots" in jsonObject -> ListRootsResult.serializer() | ||
|
|
@@ -310,7 +320,7 @@ private fun selectClientResultDeserializer(element: JsonElement): Deserializatio | |
| * Returns null if the structure doesn't match any known server result type. | ||
| */ | ||
| private fun selectServerResultDeserializer(element: JsonElement): DeserializationStrategy<ServerResult>? { | ||
| val jsonObject = element.jsonObject | ||
| val jsonObject = element.asJsonObject() | ||
| return when { | ||
| "protocolVersion" in jsonObject && "capabilities" in jsonObject -> InitializeResult.serializer() | ||
| "completion" in jsonObject -> CompleteResult.serializer() | ||
|
|
@@ -378,7 +388,7 @@ internal object ServerResultPolymorphicSerializer : | |
| internal object JSONRPCMessagePolymorphicSerializer : | ||
| JsonContentPolymorphicSerializer<JSONRPCMessage>(JSONRPCMessage::class) { | ||
| override fun selectDeserializer(element: JsonElement): DeserializationStrategy<JSONRPCMessage> { | ||
| val jsonObject = element.jsonObject | ||
| val jsonObject = element.asJsonObject() | ||
| return when { | ||
| "error" in jsonObject -> JSONRPCError.serializer() | ||
| "result" in jsonObject -> JSONRPCResponse.serializer() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| ## https://docs.junit.org/5.3.0-M1/user-guide/index.html#writing-tests-parallel-execution | ||
| junit.jupiter.execution.parallel.enabled=true | ||
| junit.jupiter.execution.parallel.config.strategy=dynamic | ||
| junit.jupiter.execution.parallel.mode.default=concurrent | ||
| junit.jupiter.execution.parallel.mode.classes.default=concurrent | ||
| junit.jupiter.execution.timeout.default=2m |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Level of logging for the ROOT logger: ERROR, WARN, INFO, DEBUG, TRACE (default is INFO) | ||
| org.slf4j.simpleLogger.defaultLogLevel=INFO | ||
| org.slf4j.simpleLogger.showThreadName=true | ||
| org.slf4j.simpleLogger.showDateTime=false | ||
|
|
||
| # Log level for specific packages or classes | ||
| org.slf4j.simpleLogger.log.io.ktor.server=INFO | ||
| org.slf4j.simpleLogger.log.io.modelcontextprotocol=DEBUG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would make more sense to put this in the json utils file and make the function as internal