question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] Can't figure out sealed class polymorphism with protobuf

See original GitHub issue

Target code:

//@Polymorphic
@Serializable
sealed class Request {

    @Serializable
    @SerialName("StockHistory")
    data class StockHistory(
        @Polymorphic @Required val ticker: String,
        @Polymorphic @Required val hours: Int
    ) : Request()



    companion object {
        val protoBuf = ProtoBuf(SerializersModule {
            polymorphic(Request::class) {
                addSubclass(StockHistory.serializer())
            }
        })
    }
    
}

Main:

println(Request.protoBuf.load<Request>(Request.protoBuf.dump(Request.StockHistory("BTCs", 10))))

This results in this error: class kotlin.String is not registered for polymorphic serialization in the scope of class kotlin.String

I can’t seem to piece together what I’m doing wrong, I also tried doing this without the experimental “ImplicitReflectionSerializer” stuff, results in the same issue.

Any help is greatly appreciated.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
sandwwraithcommented, Feb 26, 2020

You need to remove @Polymorphic @Required from val ticker and hours, because you don’t want to serialize ticker and hours polymorphically, right? String always has one implementation, since it is a final class.

Also, correct form of dump would be Request.protoBuf.dump(Request.serializer(), Request.StockHistory("BTCs", 10)) (or dump<Request>(...)) – you need to use Request.serializer(), not Request.StockHistory.serializer(), since only the sealed class serializer knows about all hierarchy.

Unfortunately, due to #721 bug, you may experience java.lang.ArrayIndexOutOfBoundsException: 1 with a [funny] workaround of adding additional class. So final correct code would look like:

@Serializable
sealed class Request {

    @Serializable
    @SerialName("StockHistory")
    data class StockHistory(
        val ticker: String,
        val hours: Int
    ) : Request()

    @Serializable
    class Unused: Request()

    companion object {
        val protoBuf = ProtoBuf()
    }
}

println(Request.protoBuf.load<Request>(Request.protoBuf.dump<Request>(Request.StockHistory("BTCs", 10))))
// prints StockHistory(ticker=BTCs, hours=10)
0reactions
camdenorrbcommented, Feb 27, 2020

@sandwwraith Thank you so much! The array out of bounds exception really threw me off when I got it from experimenting. Glad this is all clear now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does protocol buffers supports polymorphism (In java at least) ?
The main problem is that you cannot passed a sub class to an interface the is defined as accepting super classes and expect...
Read more >
what's the right way to do polymorphism with protocol buffers?
Yes you can just use HasExtension to find out if a given Animal message contains a Cat or Dog extension. – Jamie Flournoy....
Read more >
Protocol Buffers | Jon Skeet's coding blog
A question came up on Stack Overflow yesterday which I've had to deal with myself before now. There are times when it's helpful...
Read more >
kotlinx.serialization
This class provides support for multiplatform polymorphic serialization for interfaces and ... If you cannot avoid using internal API to solve your problem, ......
Read more >
What Is Object-Oriented Programming? | by Umair Feroze
Abstract classes may have a constructor. Abstract vs Sealed. A sealed class prevents a class from being extended or inherited. It cannot be ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found