Skip to content
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

[Bug] Inline value class can be successfully serialized to a json string, but fails to be deserialized from a json string ! #2929

Closed
hehua2008 opened this issue Feb 17, 2025 · 1 comment

Comments

@hehua2008
Copy link

Describe the bug
A inline value class SpecificTool, implementing a sealed interface ToolChoice, can be successfully serialized to a json string, but fails to be deserialized from a json string !

Test code

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable
data class Request(
    /**
     * Controls tool usage: `none`, `auto`, `required`, or specific tool.
     */
    @SerialName("tool_choice") val toolChoice: ToolChoice? = null,
)

@Serializable
sealed interface ToolChoice {
    @Serializable
    @JvmInline
    value class StringTool(val value: String) : ToolChoice

    @Serializable
    data class SpecificTool(
        /**
         * Type of tool choice: `function`.
         */
        @SerialName("type") val type: String = "function",
        /**
         * Function to call.
         */
        @SerialName("function") val function: FunctionChoice
    ) : ToolChoice {
        @Serializable
        data class FunctionChoice(
            /**
             * Name of the function to call.
             */
            @SerialName("name") val name: String
        )
    }
}

fun main() {
    val jsonDefault = Json {
        classDiscriminator = "json_class_type"
        ignoreUnknownKeys = true
        encodeDefaults = true
    }

    val stringTool = ToolChoice.StringTool("auto")
    val request1 = Request(stringTool)
    val request1_json = jsonDefault.encodeToString(request1)
    println(request1_json)

    val specificTool = ToolChoice.SpecificTool("function", ToolChoice.SpecificTool.FunctionChoice("testFunction"))
    val request2 = Request(specificTool)
    val request2_json = jsonDefault.encodeToString(request2)
    println(request2_json)

    val request2New = jsonDefault.decodeFromString<Request>(request2_json)
    println(request2New)

    val request1New = jsonDefault.decodeFromString<Request>(request1_json)
    println(request1New)
}

Test output

{"tool_choice":"auto"}
{"tool_choice":{"json_class_type":"ToolChoice.SpecificTool","type":"function","function":{"name":"testFunction"}}}
Request(toolChoice=SpecificTool(type=function, function=FunctionChoice(name=testFunction)))
Exception in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Expected JsonObject, but had JsonLiteral as the serialized body of ToolChoice at element: $.tool_choice
JSON input: "auto"
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:400)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
	at Request$$serializer.deserialize(main.kt:5)
	at Request$$serializer.deserialize(main.kt:5)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
	at MainKt.main(main.kt:67)
	at MainKt.main(main.kt)

Expected behavior

{"tool_choice":"auto"}
{"tool_choice":{"json_class_type":"ToolChoice.SpecificTool","type":"function","function":{"name":"testFunction"}}}
Request(toolChoice=SpecificTool(type=function, function=FunctionChoice(name=testFunction)))
Request(toolChoice=StringTool(value=auto))

Environment

  • Kotlin version: 2.1.0
  • Library version: 1.8.0
  • Kotlin platforms: JVM, may be same in JS, Native
  • Gradle version: 8.9
  • IDE version: Android Studio 2024.2.2
  • Other relevant context [e.g. OS version, JRE version, ... ]
@sandwwraith
Copy link
Member

Duplicate of #2835. See #2049 (comment) for context.

@sandwwraith sandwwraith closed this as not planned Won't fix, can't repro, duplicate, stale Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants