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.

Serialization of Guava optional with polymorphic inner class is not including @class as specified by @JsonTypeInfo

See original GitHub issue

Describe the bug Serialization of Guava optional with polymorphic inner class is not including @class as specified by @JsonTypeInfo

It works correctly on Jackson 2.6.5, but stopped working at some point since then. For compatibility reasons our Android app has been locked Jackson 2.6.5 and we only noticed this once server was recently upgrade to 2.13.1 and our integration tests started failing because they use a retrofit client that uses the latest version of jackson.

Version information 2.13.1

To Reproduce Here is the interface

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY, property="@class")
public interface SourceDevice {

}

Here is the concrete class

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY, property="@class")
public class AndroidDevice implements SourceDevice {
    private final String              device;
    private final String              model;
    private final String              codename;
    private final String              brand;
    private final String osVersion;
    private final String              sdkVersion;
    private final String              product;
    private final String              deviceId;
    private final Map<String, Object> additionalInfo;

    @JsonCreator
    public AndroidDevice(
            @JsonProperty( DEVICE ) String device,
            @JsonProperty( MODEL ) String model,
            @JsonProperty( CODENAME ) String codename,
            @JsonProperty( BRAND ) String brand,
            @JsonProperty( OS_VERSION ) String osVersion,
            @JsonProperty( SDK_VERSION ) String sdkVersion,
            @JsonProperty( PRODUCT ) String product,
            @JsonProperty( DEVICE_ID ) String deviceId,
            @JsonProperty( ADDITIONAL_INFO ) Optional<Map<String, Object>> additionalInfo ) {
        this.device = device;
        this.model = model;
        this.codename = codename;
        this.brand = brand;
        this.osVersion=osVersion;
        this.sdkVersion = sdkVersion;
        this.product = product;
        this.deviceId = deviceId;
        this.additionalInfo = additionalInfo.or( HashMap::new );
    }
}

The setup for the object mapper:

mapper.registerModule( new GuavaModule() );
mapper.registerModule( new JodaModule() );
mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );

Our actual serialization test is here: https://github.com/openlattice/chronicle-server/blob/18be3bfc845445e20b3fdc1094c5e8194d49c1ae/src/test/kotlin/com/openlattice/chronicle/serialization/SourceDeviceSerializationTest.kt

Base serialization test class is here: https://github.com/geekbeast/rhizome-client/blob/da2c8807fc4b8fa085375a58502db47baa6f36fb/src/test/java/com/geekbeast/serializer/serializer/AbstractJacksonSerializationTest.java

Expected behavior Expected behavior is the following json string:

{"@class":"com.openlattice.chronicle.sources.AndroidDevice","device":"650ad51cf4a84729","model":"Android SDK built for x86","codename":"REL","brand":"Android","osVersion":"30","sdkVersion":"30","product":"sdk_phone_x86","deviceId":"650ad51cf4a84729","additionalInfo":{}}

Instead here is what is serialized:
{"device":"650ad51cf4a84729","model":"Android SDK built for x86","codename":"REL","brand":"Android","osVersion":"30","sdkVersion":"30","product":"sdk_phone_x86","deviceId":"650ad51cf4a84729","additionalInfo":{}}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Feb 28, 2022

While I won’t yet close this issue, I think that the eventual evaluation will be that of later Jackson versions working as expected; while 2.6 did work the way that was good in your case it is unfortunately incompatible with the way polymorphic handling overall works.

2.7+ handling can be made to work with polymorphic contents of Optionals as suggested by above changes, however.

0reactions
cowtowncodercommented, Feb 28, 2022

Ok good @geekbeast thank you for the update. It is good that you can work around this problem. It is unfortunate there is this discontinuity, but supporting Optional has been challenging as there are (at least) 2 ways to go about it. And initial implementation did not fully consider polymorphic handling of contents either.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can Jackson polymorphic deserialization be used to serialize ...
I want to use polymorphic deserialization to construct Animal instances if no wingspan is specified, and Bird instances if it is. In Jackson, ......
Read more >
Annotation Type JsonTypeInfo - Red Hat Customer Portal
This annotation can be used both for types (classes) and properties. If both exist, annotation on property has precedence, as it is considered...
Read more >
Using unsafe Jackson deserialization configuration is security ...
Class members annotated with "@VisibleForTesting" should not be accessed ... Fields in a "Serializable" class should either be transient or serializable.
Read more >
Using @JsonTypeInfo annotation to handle polymorphic types
Let's serialize and then deserialize a View object: public class ... Id.CLASS) and persist that as JSON property (include = JsonTypeInfo.
Read more >
yawkat – Libera #java
Normal Java serialization does not have this problem (it just carries the ... The idea is simple: Include the full class name in...
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