Avoiding @type for serialization depending on the field declaration on the parent

13 views
Skip to first unread message

Pablo Pazos

unread,
Aug 12, 2019, 8:56:07 PM8/12/19
to jackson-user
Hi,

I have a model where some class attributes are concrete/final and other are generic, I want to avoid adding the @type to the concrete/final. Here is an example:

class Action {

   DvTime time;
}

class Element {

   Object value;
}

final class DvTime {

  ...
}

We could do:

Element e = new Element();
e.setValue(new DvTime(...));

Action a = new Action();
a.setTime(new DvTime(...));


When those objects are serialized, I need:

{
  @type: Element,
  value: {
    @type: DvTime,
    ...
  }
}

{
  @type: Action,
  time: {
    ...
  }
}

That avoids adding the @type = DvTime for action.time because by the model I know that always be a DvTime.

Is that possible? Thanks!

Tatu Saloranta

unread,
Aug 12, 2019, 11:46:33 PM8/12/19
to jackson-user
I think the example is missing information to fully understand
relationship between types, but in general, polymorphic type handling
is optional and only used for classes with `@JsonTypeInfo` in base
class, or annotation on property. So you can select which type
hierarchies will use type ids.

Second thing is that for deserialization, one can omit "type id" if
(but only if!) there is property `defaultImpl` for `@JsonTypeInfo`. So
that could be pointing to final implementation.
There is no matching setting (yet) to prevent outputting of type id
when polymorphic types are enabled. There is an issue to support it,
and maybe it gets eventually implemented.

Those are the existing mechanisms for selective use of type ids. But
in general types are not meant to use mix-and-match approach as that
is very difficult to support on deserialization side.

-+ Tatu +-

Pablo Pazos

unread,
Aug 13, 2019, 1:54:02 AM8/13/19
to jackson-user
Hi Tatu,
IMO all the info is there, but I have a much complex model. On the example:

Action has one DvTime
Element has one Object (this is really a DvTime superclass, I set object to avoid adding another class to the model*)

* this really would be

abstract class Dv {

}

class DvTime extends Dv {

  Date value
  ... other fields here
}

Then:

class Element {

   Dv value
}

but in general, polymorphic type handling
is optional and only used for classes with `@JsonTypeInfo` in base
class, or annotation on property. So you can select which type
hierarchies will use type ids.

I'm very new to Jackson and don't know what JsonTypeInfo is for :(

But related to the hierarchies to use, in Action.time there shouldn't be any hierarchies. And in Element.value the whole Dv hierarchy is allowed. That is why on Action.time I don't need the @type and yes on Element.value.
 

Second thing is that for deserialization, one can omit "type id" if
(but only if!) there is property `defaultImpl` for `@JsonTypeInfo`. So
that could be pointing to final implementation.

That happens on Action.time, but not sure how that is linked to JsonTypeInfo or to defaultImpl, I'm lacking experience in Jackson, sorry.
 
There is no matching setting (yet) to prevent outputting of type id
when polymorphic types are enabled. There is an issue to support it,
and maybe it gets eventually implemented.

I guess that is needed for what I need to do here. The issue I have is 1. the model is big and complex, 2. most of the relationships are final (don't really need the @type and cutting those would cut some bytes from the final JSON), 3. only few relationships (fields) are polymorphic, but on those I could have a lot of options in terms of the inheritance hierarchy.
 

Those are the existing mechanisms for selective use of type ids. But
in general types are not meant to use mix-and-match approach as that
is very difficult to support on deserialization side.

In my case I think that is easy to do by looking/inspecting (with reflection) the model, but not sure how Jackson does that internally, I guess an annotation could help there to know which fields are final, but I think that could be done with normal java reflection without any annotations. Maybe I'm wrong :)
 

-+ Tatu +-

Tatu Saloranta

unread,
Aug 23, 2019, 5:54:28 PM8/23/19
to jackson-user
It is annotation used to enable Polymorphic Type handling; explained f.ex here:

https://www.baeldung.com/jackson-inheritance

>
> But related to the hierarchies to use, in Action.time there shouldn't be any hierarchies. And in Element.value the whole Dv hierarchy is allowed. That is why on Action.time I don't need the @type and yes on Element.value.
>
>>
>>
>> Second thing is that for deserialization, one can omit "type id" if
>> (but only if!) there is property `defaultImpl` for `@JsonTypeInfo`. So
>> that could be pointing to final implementation.
>
>
> That happens on Action.time, but not sure how that is linked to JsonTypeInfo or to defaultImpl, I'm lacking experience in Jackson, sorry.
>
>>
>> There is no matching setting (yet) to prevent outputting of type id
>> when polymorphic types are enabled. There is an issue to support it,
>> and maybe it gets eventually implemented.
>
>
> I guess that is needed for what I need to do here. The issue I have is 1. the model is big and complex, 2. most of the relationships are final (don't really need the @type and cutting those would cut some bytes from the final JSON), 3. only few relationships (fields) are polymorphic, but on those I could have a lot of options in terms of the inheritance hierarchy.

Saving some bytes may be nice thing to have, but in case of type id
handling tends to

1. Cause massive complexity in handling code if it tries to figure
when, how and why type id might be missing
2. Lead to unexpected, hard to diagnose failures due to complexity.

Given this, Jackson really does not try to be clever and omit (or
ignore) type information:
generally a property either HAS to have (and does use) type ids, or
does not use or have those. There is that one little exception to
support edge cases wherein even if Type Id is expected, it MAY be
omitted if (and only if) a default implementation is defined
(`defaultImpl` property of `@JsonTypeInfo`)

-+ Tatu +-
Reply all
Reply to author
Forward
0 new messages