-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Support Lombok's fluent setters in reflection-free Jackson serialization #46647
Comments
/cc @geoand (jackson), @gsmet (jackson), @mariofusco (jackson) |
Does it work properly without the reflection free seriaiizers? |
Yes it does! Note: I have I tried to migrate to reflection-free to check performance, and also because I'm migrating my apps in native and I don't want to add |
Maybe attach a small project with a test that works with standard Jackson and doesn’t with the serialization free approach. |
That would be the best |
ReproducerReproducer: https://github.com/jdussouillez/quarkus-reflection-free-serialization-lombok Run Then run
Implementation details:
Generated codeHere's the generated code for the deserializer for classic POJO : public class UserClassic$quarkusjacksondeserializer extends StdDeserializer {
// ...
public Object deserialize(JsonParser var1, DeserializationContext var2) throws IOException, JacksonException {
// ...
while (var4.hasNext()) {
// ...
if (!var8.isNull()) {
// ...
switch (var7) {
case 3355:
if ("id".equals(var6)) {
int var10 = var8.asInt();
var9.setId(var10); // <------------------ Id set here
}
break;
case 3373707:
if ("name".equals(var6)) {
String var11 = var8.asText();
var9.setName(var11); // <------------------ Name set here
}
}
}
}
return var9;
}
} And here's the deserializer for the POJO using fluent setters: public class UserFluent$quarkusjacksondeserializer extends StdDeserializer {
// ...
public Object deserialize(JsonParser var1, DeserializationContext var2) throws IOException, JacksonException {
// ...
while (var4.hasNext()) {
// ...
if (!var8.isNull()) {
Object var6 = var5.getKey();
int var7 = var6.hashCode();
switch (var7) {
case 3355:
if ("id".equals(var6)) {
var8.asInt(); // <------------------ Id not set here!
}
break;
case 3373707:
if ("name".equals(var6)) {
var8.asText(); // <------------------ Name not set here!
}
}
}
}
return var9;
}
} As you can see, the deserializer never writes the value in the POJO in fluent mode because of the implementation of JacksonDeserializerFactory::isSetterMethod: private boolean isSetterMethod(MethodInfo methodInfo) {
return Modifier.isPublic(methodInfo.flags()) && !Modifier.isStatic(methodInfo.flags())
&& methodInfo.returnType() instanceof VoidType && methodInfo.parametersCount() == 1
&& methodInfo.name().startsWith("set");
} What's intriguing is that the setters using Possible solutionsNote: 1. Adapt
|
Thanks a lot for the great analysis @jdussouillez! I'll leave it to @mariofusco to decide how best to proceed |
Description
I recently tried to use reflection-free Jackson serialization but I realized it doesn't work with Lombok's fluent setters (= not prefixed with
set
).This generates my setter as
id(String id)
instead ofsetId(String id)
, so Quarkus'sJacksonDeserializerFactory::isSetterMethod
doesn't treat that as a setter method.Possible workarounds:
fluent
modefluent
mode but add prefixed setters to classesImplementation ideas
I guess the easiest solution would be to detect if the class contains fluent setters but I guess it's not that easy...
Lombok only adds
lombok.Generated
annotation on generated setters (it's added by default but it can be disabled).Another implementation would be to have a configuration options, such as
quarkus.lombok.fluent-accessors=true
.The text was updated successfully, but these errors were encountered: