kotlinx.serialization: Can't serialize instances of class hierarchy with constructor parameters
What is your use-case and why do you need this feature?
I have a web app that displays some complex reports. There is a class hierarchy of “queries” that I’d like to serialize to/from server. But something like this is not serializable:
abstract class Query(val type: QueryType) { ... }
abstract class QueryBase(type: QueryType) :Query(type) { ... }
class SpecificQuery1() : QueryBase(QueryType.Specific1) { ... }
The error is:
This class is not serializable automatically because it has primary constructor parameters of which are not properties
The type sort of is a property - it becomes a property once it’s passed up to the root class.
I put a custom serializer on QueryBase, with method bodies of TODO("not implemented"), because I’m not sure yet how I could do it, or if it’s possible.
@Serializable(with = QueryBaseSerializer::class)
abstract class QueryBase(queryType: QueryType)
I then get another error on SpecificQuery1, suggesting that even if I figured out how to write a serializer for QueryBase, I will have more problems.
Impossible to make this class serializable because its parent is not serializable and does not have exactly one constructor without parameters
Describe the solution you’d like
I’d like the auto-generated serializers to handle it. If that’s not possible, I’d like documentation on how to implement custom serializers to handle it. If I need to write custom serializers, it would be nice if there were a way to use some of the plugin’s code-generation abilities, so that I don’t have to remember to manually serialize each property and keep that code in sync if I add properties to a class. In other words, maybe the plugin can’t generate the whole serializer for me, but it could generate something to serialize the properties that it can handle, so I could call that from my serializer once I handled the custom part.
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 26
- Comments: 26 (5 by maintainers)
Hi, Unfortunately, handling arbitrary arguments that are not properties is not an easy task — because they may be involved in arbitrary expressions that should be default values or superclass constructor arguments (e.g. you have
class QueryBase(type: QueryType) :Query(type + "myQuery"))We usually recommend follow this pattern when serializing class hierarchies: make
vals abstract in base classes and override them in concrete classes, like this:What is wrong with his post? Do you expect him to be sunshine and rainbows when something this garbage pops up?
This is a clear problem that is fundemental and should have been addressed at the start.
“Feeling good” has nothing to do with it. He was nothing but polite in his post, respectfully stating his dissapointment. As he should. You want to see unpolite,
Here you go:
This is, trash. A programmer should not be forced to redo his code because a damn SERIALIZER cant serialize. Being opinionated is fine but being opinionated to the point of not working is a high horse that you have to get out of. Jetbrains is a great company and this is clearly a mistake or oversight. We should call out these things when we see them, and celebrate the things that we like. Thats how it works , cry more.
I’d like to bump this feature request, it would be really useful in my case.
I have configuration files that are shared between multiple services. All services configurations have a lot of values in common, stored in one abstract class, then each service defines a subclass adding some specific properties.
It is not a polymorphic serialization in the sense that I know which subclass I am deserializing.
@mattiasflodin The fact they get paid for this doesn’t change the fact the library is provided for free.
You should always provide the feedback, but it’s important to do it carefully, and without harm.
I think my message is very simple.
Let’s stop discussing this since at this point it’s just off topic.
@mattiasflodin I understand yours and everyone else’s disappointment, but please remember that this library is open source, and is given for free. When reading your comment, the developers of kotlinx serialization won’t feel good, and it will probably make them less motivated. I’m sure that if this issue could be solved easily, they would solve it. I can see you are an open source maintainer yourself, so you probably know how it feels.
Just a friendly reminder for everyone to be polite 🙂
Honestly I’m really surprised that this wasn’t part of the original architecture of serialization. I expected more from JetBrains. It’s an obvious and really common use case. Not sure how you expect the library to be relevant at all if class hierarchies are not handled gracefully.
Just to clarify: calling something ‘garbage’ or ‘trash’ does not raise issue priority 😃
I’m getting this error with a
sealed classhierarchy:I can apply the
abstract valstrategy as suggested by @sandwwraith , but in some cases that doesn’t make sense from a data representation / encapsulation point of view, because the object creator can override a set value in the constructor.I think the following should work correctly:
Am I doing something wrong?
Are we still speaking in good faith here? Because it seems to me you are intentionally pretending not to see the bigger picture. But I’ll humor you: The people who develop the kotlin serialization library have a salary, and without that salary the serialization library would not have seen the light of day. The salary is paid for with the sale of JetBrains products. Shareholders are happy with this arrangement because the library (if designed properly) could make the ecosystem more popular, which feeds back into more sales of JetBrains products.
However, if JetBrains develops libraries that are not useful then the investment will not lead to more sales, possibly even reduced sales because poorly designed libraries causes customers to lose trust in the company. This could lead to an increased price relative to the value you get for JetBrains products, because a disproportionate amount of the cost is wasted on software that does not increase the value of the products or even harms their value.
I have a very high trust in JetBrains. It has some of the best developers I can think of, the entire company including the support staff has an impressive technical skill, and their company processes seem to be a very well-oiled machine. So when they make mistakes like this, it makes me reevaluate that trust. Did they drop the ball? Are they going to go back and fix it, or just dismiss people who bring up issues and press on?
The best way I can think of to influence JetBrains to stay on track and not fall into the enshittification trap, is to provide feedback such as this issue. The day I stop providing feedback is the day I have lost too much trust and have given up on them.
Dude if you think “i expected more from this company” is “hurting people’s feelings” Wow you got problems. Do you have the same logic with google? they make tons of stuff for free but I dont think you will be talking to them this way…
Regardless, companies are not people, and when you insult them, people need to learn to detach themselves. Jetbrains is not these devs’ life, and these devs’ skill is not jetbrains skill. Jebrains is seperate from the devs.
But even if you consider them the same. He is just stating dissapointment in a way that is real. So many SJWs around …
My case:
or
Solution:
To be honest, I already doubt the need to use kotlinx.serialization, because jackson does not have such problems. Yes, jackson does not support some things from Kotlin, but at the moment kotlinx.serialization creates more problems than it solves. Oh yes, I have a multiplatform … Okay, I’ll have to use it.
@AbdElraoufSabri Huh, isn’t that just an implementation of the pattern suggested by @sandwwraith ?