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

Cannot serialize OpenApi instance #16

Closed
lenguyenthanh opened this issue Oct 21, 2021 · 7 comments
Closed

Cannot serialize OpenApi instance #16

lenguyenthanh opened this issue Oct 21, 2021 · 7 comments

Comments

@lenguyenthanh
Copy link
Contributor

lenguyenthanh commented Oct 21, 2021

More specifically this test failed:

"Serialize MediaType success" {
    val mediaType = MediaType(
      schema = Referenced.Other(
        value = Schema(
        )
      )
    )
    val str = json.encodeToString(mediaType)
  }

With stacktrace:

lass arrow.endpoint.docs.openapi.Schema cannot be cast to class kotlin.Unit (arrow.endpoint.docs.openapi.Schema and kotlin.Unit are in unnamed module of loader 'app')
java.lang.ClassCastException: class arrow.endpoint.docs.openapi.Schema cannot be cast to class kotlin.Unit (arrow.endpoint.docs.openapi.Schema and kotlin.Unit are in unnamed module of loader 'app')
  at kotlinx.serialization.internal.UnitSerializer.serialize(Primitives.kt:79)
  at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:219)
  at arrow.endpoint.docs.openapi.ReferencedSerializer.serialize(Serializers.kt:125)
  at arrow.endpoint.docs.openapi.ReferencedSerializer.serialize(Serializers.kt:108)
  at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:219)
  at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeNullableSerializableValue(Encoding.kt:302)
  at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableValue(AbstractEncoder.kt:18)
  at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableElement(AbstractEncoder.kt:90)
  at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeNullableSerializableElement(StreamingJsonEncoder.kt:157)
  at arrow.endpoint.docs.openapi.MediaType.write$Self(OpenAPI.kt:404)
  at arrow.endpoint.docs.openapi.MediaType$$serializer.serialize(OpenAPI.kt:404)
  at arrow.endpoint.docs.openapi.MediaType$$serializer.serialize(OpenAPI.kt:404)
  at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:219)
  at kotlinx.serialization.json.Json.encodeToString(Json.kt:85)
  at arrow.endpoint.docs.openapi.ResponseSerializerTest$1$4.invokeSuspend(ResponseSerializerTest.kt:78)
  at arrow.endpoint.docs.openapi.ResponseSerializerTest$1$4.invoke(ResponseSerializerTest.kt)
  at arrow.endpoint.docs.openapi.ResponseSerializerTest$1$4.invoke(ResponseSerializerTest.kt)
  at io.kotest.core.spec.style.scopes.StringSpecRootScope$invoke$1.invokeSuspend(StringSpecRootScope.kt:58)
  at io.kotest.core.spec.style.scopes.StringSpecRootScope$invoke$1.invoke(StringSpecRootScope.kt)
  at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invokeSuspend(executions.kt:13)
  at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2$1.invoke(executions.kt)
  at io.kotest.core.internal.ExecutionsKt.wrapTestWithGlobalAssert(executions.kt:39)
  at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invokeSuspend(executions.kt:12)
  at io.kotest.core.internal.ExecutionsKt$executeWithBehaviours$2.invoke(executions.kt)
  at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invokeSuspend(executions.kt:25)
  at io.kotest.core.internal.ExecutionsKt$wrapTestWithAssertionModeCheck$2.invoke(executions.kt)
  at io.kotest.core.internal.AssertionsCheckKt.executeWithAssertionsCheck(assertionsCheck.kt:25)
  at io.kotest.core.internal.ExecutionsKt.wrapTestWithAssertionModeCheck(executions.kt:24)
  at io.kotest.core.internal.ExecutionsKt.executeWithBehaviours(executions.kt:11)
  at io.kotest.core.internal.TestCaseExecutor$executeInScope$2.invokeSuspend(TestCaseExecutor.kt:266)
  at io.kotest.core.internal.TestCaseExecutor$executeInScope$2.invoke(TestCaseExecutor.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
  at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:194)
  at io.kotest.core.internal.TestCaseExecutor.executeInScope(TestCaseExecutor.kt:260)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1$1.invokeSuspend(TestCaseExecutor.kt:232)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1$1.invoke(TestCaseExecutor.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
  at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:148)
  at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:44)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invokeSuspend(TestCaseExecutor.kt:231)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3$1.invoke(TestCaseExecutor.kt)
  at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$3.invokeSuspend(ExecutorExecutionContext.kt:77)
  at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$3.invoke(ExecutorExecutionContext.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
  at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
  at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
  at io.kotest.engine.ExecutorExecutionContext.executeWithTimeoutInterruption(ExecutorExecutionContext.kt:75)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invokeSuspend(TestCaseExecutor.kt:230)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1$3.invoke(TestCaseExecutor.kt)
  at io.kotest.mpp.ReplayKt.replay(replay.kt:18)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invokeSuspend(TestCaseExecutor.kt:225)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1$1.invoke(TestCaseExecutor.kt)
  at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$3.invokeSuspend(ExecutorExecutionContext.kt:77)
  at io.kotest.engine.ExecutorExecutionContext$executeWithTimeoutInterruption$3.invoke(ExecutorExecutionContext.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
  at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
  at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
  at io.kotest.engine.ExecutorExecutionContext.executeWithTimeoutInterruption(ExecutorExecutionContext.kt:75)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invokeSuspend(TestCaseExecutor.kt:218)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2$1.invoke(TestCaseExecutor.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:102)
  at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:148)
  at kotlinx.coroutines.TimeoutKt.withTimeout(Timeout.kt:44)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invokeSuspend(TestCaseExecutor.kt:217)
  at io.kotest.core.internal.TestCaseExecutor$executeAndWait$2.invoke(TestCaseExecutor.kt)
  at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
  at kotlinx.coroutines.SupervisorKt.supervisorScope(Supervisor.kt:57)
  at io.kotest.core.internal.TestCaseExecutor.executeAndWait(TestCaseExecutor.kt:213)
  at io.kotest.core.internal.TestCaseExecutor.invokeTestCase(TestCaseExecutor.kt:182)
  at io.kotest.core.internal.TestCaseExecutor.executeActiveTest(TestCaseExecutor.kt:151)
  at io.kotest.core.internal.TestCaseExecutor$intercept$innerExecute$1$1.invokeSuspend(TestCaseExecutor.kt:89)
  at io.kotest.core.internal.TestCaseExecutor$intercept$innerExecute$1$1.invoke(TestCaseExecutor.kt)
  at io.kotest.core.internal.TestCaseExecutor.executeIfActive(TestCaseExecutor.kt:115)
  at io.kotest.core.internal.TestCaseExecutor$intercept$innerExecute$1.invokeSuspend(TestCaseExecutor.kt:89)
  at io.kotest.core.internal.TestCaseExecutor$intercept$innerExecute$1.invoke(TestCaseExecutor.kt)
  at io.kotest.core.internal.TestCaseExecutor.intercept(TestCaseExecutor.kt:103)
  at io.kotest.core.internal.TestCaseExecutor.execute(TestCaseExecutor.kt:69)
  at io.kotest.engine.spec.runners.SingleInstanceSpecRunner.runTest(SingleInstanceSpecRunner.kt:106)
  at io.kotest.engine.spec.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$2.invokeSuspend(SingleInstanceSpecRunner.kt:56)
  at io.kotest.engine.spec.runners.SingleInstanceSpecRunner$execute$2$invokeSuspend$$inlined$invoke$lambda$2.invoke(SingleInstanceSpecRunner.kt)
  at io.kotest.engine.launchers.SequentialTestLauncher$launch$$inlined$forEach$lambda$1$1.invokeSuspend(SequentialTestLauncher.kt:22)
  at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
  at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
  at java.base/java.lang.Thread.run(Thread.java:832)

It failed when serializing Referenced type. But the stand alone test for Referenced works fine:

  "Referenced.Other serialize" {
    val schema = Referenced.Other(
      Schema()
    ) as Referenced<Schema>
    val str = json.encodeToString(schema)
  }
@nomisRev
Copy link
Member

The whole serialization should get hidden behind the API and KotlinX Serialization should not be exposed.
Since the produced json cannot be decoded back to OpenAPI due to how the OpenAPI Spec works.

@lenguyenthanh
Copy link
Contributor Author

Because of this failure the current example doesn't work. Do you have any idea how to fix this @nomisRev? I think it is related to a kotlinx serialization bug, but I couldn't find it now.

And I totally agree with you point about hiding this from public api.

@nomisRev
Copy link
Member

It seems to be picking up Seriliazer for Unit for the Encoder for Schema... Strange.

What is the use-case for converting MediaType to JSON?

Would we be able to close this issue if we make KotlinX Serialization internal and only expose OpenAPI#toJson

@lenguyenthanh
Copy link
Contributor Author

lenguyenthanh commented Oct 25, 2021

Actually OpenAPI#toJson leads to this issue anyway. That's why I discovered this bug. You can see the error by running the current example.

@nomisRev
Copy link
Member

Do you have a snippet that reproduces this with OpenAPI#toJson?

I tried to take a quick look to try and figure out what's going wrong. Seems that something is going wrong when resolving the generic serializer in KotlinX Serialization.

So not sure what is wrong yet, perhaps we have to explicitly register some of the polymorphic serializers.

@nomisRev
Copy link
Member

@lenguyenthanh if you have any meaningful tests (even failing ones) or code, a PR is always welcome for it :)

@lenguyenthanh
Copy link
Contributor Author

@nomisRev yeah, it seems there is a bug in Kotlinx Serialization like you said earlier: It seems to be picking up Seriliazer for Unit for the Encoder for Schema... Strange.

I have some failed tests for it, will create a PR soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants