maybe I'm missing some important piece or my thinking is a bit too naïve, but I try to write a generic message passing library based on a json protocol.
package com.fasterxml.jackson.module.kotlin.test.github
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.exc.MismatchedInputException
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import junit.framework.TestCase.assertEquals
import org.junit.Assert.assertThrows
import kotlin.test.Test
class ReproductionTest {
@JsonTypeInfo(use = JsonTypeInfo.Id.SIMPLE_NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
sealed class Response<out Err, out B>{
data class Success<out B>(val response: B) : Response<Nothing, B>()
data class Failure<out Err>(val error: Err) : Response<Err, Nothing>()
}
@JsonTypeInfo(use = JsonTypeInfo.Id.SIMPLE_NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
sealed class Message {
data class Text(val text: String) : Message()
data class Image(val url: String) : Message()
}
@JsonTypeInfo(use = JsonTypeInfo.Id.SIMPLE_NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
sealed class Error {
data class NotFound(val message: String) : Error()
data class BadRequest(val message: String) : Error()
}
val asJson = """{"@type":"Success","response":{"@type":"Text","text":"foo"}}"""
val responseSuccess: Response<Error, Message> = Response.Success(Message.Text("foo"))
@Test
fun testReadAsValue() {
val mapper = jacksonObjectMapper()
val refType = mapper.typeFactory.constructParametricType(Response::class.java, Error::class.java, Message::class.java)
// Failing com.fasterxml.jackson.databind.exc.InvalidTypeIdException:
// Could not resolve type id 'Success' as a subtype of ...
assertEquals(
responseSuccess,
mapper.readValue<Response<Error, Message>>(asJson, refType)
)
}
@Test
fun testWriteAsValue() {
val mapper = jacksonObjectMapper()
// Failing
assertEquals(
asJson,
mapper.writeValueAsString(responseSuccess) // actual: {"@type":"Success","response":{"text":"foo"}}
)
}
}
My expectations/goals would be:
if defined at the root type of Err/B type information should be included in the "response": {...} value and should be in control of the consuming code side (Message & Error would be defined there). But the type information is missing the the serialized value
and of course it should be deserializable
Is that possible to achieve? I tried various variations, including mapper.writerFor(refType), without any success.
Your question
Hi,
maybe I'm missing some important piece or my thinking is a bit too naïve, but I try to write a generic message passing library based on a json protocol.
My expectations/goals would be:
"response": {...}
value and should be in control of the consuming code side (Message
&Error
would be defined there). But the type information is missing the the serialized valueIs that possible to achieve? I tried various variations, including
mapper.writerFor(refType)
, without any success.Help is appreciated!
Greetings