Why would Jackson be omitting type information for serialized polymorphic types when using ProGuard? #4981
Replies: 3 comments 17 replies
-
We could flip this on its head, why is proguard stopping jackson from working? Can you not go to proguard experts for this? There is no proguard expertise in the Jackson team. |
Beta Was this translation helpful? Give feedback.
-
It is probably easiest to simply disable obfuscation for your model classes. It wouldn't hide much anyway given that the relevant names still have to be there for the serialization to work, be it as actual element names or in a json string somewhere. That said, this is not really a jackson issue. Jackson just uses reflection to look at type and field names. If you use proguard to rename those types and fields, of course the serialized representation is also going to change, there is nothing jackson can do about it. |
Beta Was this translation helpful? Give feedback.
-
The solution was small but subtle. To make code like this example work correctly after obfuscation you must instruct ProGuard to keep the "Signature" data of the original bytecode. Changing this line from
to this:
allows the example to run successfully even after obfuscation. The description of It's not clear to me what the "obfuscation theory" or tradeoffs involved in keeping that data nor why ProGuard's default configuration does not keep it. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
[Also asked on SO here]
In a project that's being obfuscated with ProGuard (using the Gradle plugin), I have lots of serialization/deserialization using Jackson. I've found that in the obfuscated builds, certain kinds of serialization of polymorphic types is omitting the type information (specified with
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
), which causes some very strange behavior during deserialization.For example, here's the (correct) serialized form when run with unobfuscated code:
Here's the output of the exact same code after running through ProGuard:
Note the
"type"
property is missing from the array elements in the obfuscated form. This causes Jackson to deserialize those objects incorrectly.Here is an MRE of the code; sorry for including so much code in a question, but this is as minimal as I could get it and still demonstrate the context and problem.
Also viewable as a gist.
Here's the Gradle build file with ProGuard configuration:
Run
./gradlew jar
to build, you'll get a normal (unobfuscated) JAR. Run./gradlew proguard jar
and the resulting JAR will be obfuscated. Either way, you can then run withjava -jar ...
Here's what happens with each.
Unobfuscated:
Output using the obfuscated build:
The
ClassCastException
indicates that thecars
List is actually populated with LinkedHashMap instances rather than CarModel instances as it should. But I guess that makes sense given the serialized form that's missing type information - I suppose Jackson is just deserializing that into maps since it doesn't have the actual expected type at runtime (thanks, stoopid type erasure!).If I change
Inventory.cars
to be aCarModel[]
instead ofList<CarModel>
then it works even when obfuscated. However, that's not feasible in the real application project and the number of places this problem occurs.The real question is, why is Jackson omitting the type info from the serialized form when the code has been obfuscated? What could obfuscation be doing that causes Jackson to lose the type info, and what can I do about it?
Beta Was this translation helpful? Give feedback.
All reactions