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

Auto-detect sealed classes (similar to @JsonSubTypes) #239

Closed
shartte opened this issue Jul 24, 2019 · 4 comments
Closed

Auto-detect sealed classes (similar to @JsonSubTypes) #239

shartte opened this issue Jul 24, 2019 · 4 comments
Milestone

Comments

@shartte
Copy link
Contributor

shartte commented Jul 24, 2019

I am not sure whether this is actually possible given Jacksons API, but I'd like to avoid having to specify the @JsonSubTypes annotation when working with polymorphic sealed classes.

Here's an example that'll work with the current module:


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes(
        JsonSubTypes.Type(Either.A::class, name = "a"),
        JsonSubTypes.Type(Either.B::class, name = "b")
)
sealed class Either {

    data class A(var field: String = "") : Either()

    data class B(var otherField: String = "") : Either()

}

But here's how I'd like it to look:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
sealed class Either {

    @JsonTypeName("a")
    data class A(var field: String = "") : Either()

    @JsonTypeName("b")
    data class B(var otherField: String = "") : Either()

}

This should be possible given that Kotlin exposes the sealed class's subclasses as Either::class.sealedSubclasses.

And here's a test function:

fun main() {

    val mapper = ObjectMapper()
    val either = mapper.readValue<Array<Either>>("""[
        {
            "@type": "a",
            "field": "value"
        },
        {
            "@type": "b",
            "otherField": "1234"
        }
    ]""")
    println(either.contentToString())

}
@cowtowncoder
Copy link
Member

I don't know of feasibility on Kotlin module side, but since discovery of subtypes (usually based on @JsonSubTypes) is pluggable via AnnotationIntrospector, this seems potentially doable.
In case anyone might have time & itch to try it. I can help with details of discovery process as need be, but do not know Kotlin (or its runtime) well, nor have time to drive this.

@shartte
Copy link
Contributor Author

shartte commented Jul 24, 2019

@cowtowncoder I've opened a PR that implements this, including a test for both implicit and explicit specification of subtypes.

@cowtowncoder
Copy link
Member

Now that was quick!

@cowtowncoder cowtowncoder modified the milestones: 2.10, 2.10.0.pr2 Aug 1, 2019
@cowtowncoder cowtowncoder changed the title Make @JsonSubTypes unnecessary when using sealed classes Auto-detect sealed classes (similar to @JsonSubTypes) Aug 1, 2019
cowtowncoder added a commit that referenced this issue Aug 1, 2019
@araujogo
Copy link

araujogo commented Nov 7, 2019

It`s too bad we have to write the subtype name twice when the property name is the same os the object name. This is what I have to do:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "value")
sealed class Plano(val displayName: String) : SelectField() {
    @JsonTypeName("Bas")
    object Bas : Plano("Básico")
    @JsonTypeName("Emp")
    object Emp : Plano("Empresarial")
    @JsonTypeName("Ext")
    object Ext : Plano("Extra")
}

Shouldn't be a way to use the exactly class name (without leading points and outer types) as in JsonTypeInfo.Id.MINIMAL_CLASS ? It would be a lot cleaner for people who are converting ENUMs to sealed (which the client API is already defined)

Nthalk added a commit to Nthalk/typescript-generator that referenced this issue Jan 17, 2023
Java language level 17 and above supports isSealed on member types.

This uses the proposal of FasterXML/jackson-module-kotlin#239 and the general solution of FasterXML/jackson-module-kotlin#240 to import subtypes of a sealed object or interface that are annotated with `@JsonTypeName` and assignable to the container class or interface to create a much less verbose method of generating tagged unions.
Nthalk added a commit to Nthalk/typescript-generator that referenced this issue Jan 17, 2023
This uses the proposal of FasterXML/jackson-module-kotlin#239 and the general solution of FasterXML/jackson-module-kotlin#240 to import subtypes of a sealed object or interface that are annotated with `@JsonTypeName` and assignable to the container class or interface to create a much less verbose method of generating tagged unions.

Sealed types are supported in kotlin 1.6+ and Java 17+, however, we don't really need the sealed functionality, as we are an offline, one-shot generator, this may work to generate the correct type mappings, but fail to parse on the runtime object mapper side unless the user is using the supported kotlin and java versions.
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

3 participants