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

Sealed hierarchy of case classes serialization won't work #289

Open
edmondop opened this issue Oct 13, 2016 · 7 comments
Open

Sealed hierarchy of case classes serialization won't work #289

edmondop opened this issue Oct 13, 2016 · 7 comments

Comments

@edmondop
Copy link

Sealed hierarchy of case classes are widely used in Scala, however in Jackson-Scala they don't seem to be supported.

We are looking for a workaround: when we try to add custom serializers / deserializers for our sealed trait and then use the default "serializers" for the subclasses, the serializers/deserializers for the trait take higher priority and this results in a Stackoverflow error.

Is there a solution for this?

@nbauernfeind
Copy link
Member

Can you provide a more thorough example of your case class structure? I'm not understanding why it doesn't work without custom serializers/deserializers in the first place.

The case class serializer is found very early in the class hierarchy. When it later stumbles upon your custom serializer it uses that since it appears more specific than the generic case class one it found earlier.

@a-e-tsvetkov
Copy link

a-e-tsvetkov commented Jun 6, 2018

EDIT
My first thought was wrong. Problem I described is not the same that described in issue .
ORIGINAL
As far as I understand we talk about following situation:

case class Wrapper(v: Type)
sealed trait Type
case class TypeA(v: String) extends Type
case object TypeB extends Type

When Wrapper(TypeA("1")) is serialized we expect:

{
   "v": {
      "type": "TypeA",
      "value": {
         "v": "1"
      }  
   }
}

because otherwise it will be impossible to deserialize it properly.

I looked into code and found that jackson is unable to handle this situation.
We can try to check that object to be serialized is of class that extends sealed trait and create propper serializer, but it will break usecase when we directly reference to such case class. Like that:

case class Wrapper(v: TypeA)
sealed trait Type
case class TypeA(v: String) extends Type
case object TypeB extends Type

Because in this situation we do not need to serialize type information.

And jackson doesn't store context in which class is used, so "there is no hope for us".

@nbauernfeind
Copy link
Member

@a-e-tsvetkov
Copy link

a-e-tsvetkov commented Jun 6, 2018

I tried but

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
)
@JsonSubTypes(Array(
  new Type(value = classOf[TypeA]),
  new Type(value = classOf[TypeB])
)
)
sealed trait Some
case class TypeA(v: String) extends Some
case object TypeB extends Some

compilation failed

[ERROR] /home/atcvetkov/project/dummy/dummy-scala/src/main/scala/dummy/App.scala:27: error: not found: type TypeB
[INFO]   new Type(value = classOf[TypeB])
[INFO]                            ^

@nbauernfeind
Copy link
Member

TypeB in the code you provided is an object not a class. The proper way to get the class of an object is the TypeB.getClass. Unfortunately the type info annotation requires the value be constant which means you can't call getClass() on TypeB's singleton/object. Though they are discouraged, have you considered using parameter-less case classes instead of case objects?

@a-e-tsvetkov
Copy link

Yes. It will solve the problem, but I thing they are discouraged for a reason (unknown for me), so I just created custom serializer and deserializer for sealed trait.
It is possible to create generic one, but it will have numbers of restriction and not so obvious problem. I don't think it is good idea to include such generic serializer and deserializer in this (or some other) library.

@nbauernfeind
Copy link
Member

The plan has always been to add "real" scala support in scala 2.12 once we had access to a real scala reflection API. Now that it's available no one has really had much time to make it happen. As of right now, though, this is just not possible yet.

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