-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Handle Enum
introspection of values and aliases via AnnotatedClass
instead of Class<?>
#3832
Handle Enum
introspection of values and aliases via AnnotatedClass
instead of Class<?>
#3832
Conversation
src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
Outdated
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
Outdated
Show resolved
Hide resolved
Ok, so I probably should have mentioned earlier that I do not want mix-in handling logic to be added outside of where it is done currently. So (de)serializers, factories that produce them should ideally not have to know anything about existence of mix-ins but would rather just look for annotations. Part of the challenge is that otherwise We can leave this PR open, just in case my thinking evolves. I realize that structure of Enum types as bytecode is kind of interesting and challenging to reconcile with POJOs, for example. |
@cowtowncoder Thinking further, I think what you saying is this -- Why @JsonProperty and @JsonAlias annotations from a mix-in class do not override those from the deserialization target class for Enum types, as Enum classes have a different nature than POJOs that prevents using POJO mix-in handling on them. |
|
…yukKim/jackson-databind into 2787-allow-mixins-for-enums
…yukKim/jackson-databind into 2787-allow-mixins-for-enums
src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedFieldCollector.java
Outdated
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
Outdated
Show resolved
Hide resolved
Ok aside from that |
src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
Outdated
Show resolved
Hide resolved
Great, sounds like a plan! 👍🏻 For the meantime, is there anything I can do to make our change more stable? |
No, just need to figure out how to remove special handling from |
src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
Outdated
Show resolved
Hide resolved
Enum
sEnum
values and aliases with Annotated class
Enum
values and aliases with Annotated classEnum
values and aliases with AnnotatedClass
Enum
values and aliases with AnnotatedClass
Enum
values and aliases via AnnotatedClass
instead of Class
Enum
values and aliases via AnnotatedClass
instead of Class
Enum
values and aliases via AnnotatedClass
instead of Class<?>
Enum
values and aliases via AnnotatedClass
instead of Class<?>
Enum
introspection of values and aliases via AnnotatedClass
instead of Class<?>
I shifted direction of this PR and modified PR title and description accordingly, after studying this issue. May I ask for your opinion, @cowtowncoder? |
src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
Show resolved
Hide resolved
@JooHyukKim I hope to get back to this one Really Soon Now -- and I think your approach looks good from what I see. Thank you once again for doing such a good job in taking feedback and finding ever improving solutions. I REALLY appreciate your diligence and persistence. |
public String[] findEnumValues(MapperConfig<?> config, Enum<?>[] enumValues, String[] names, | ||
AnnotatedClass annotatedClass) { | ||
// First collect all JsonProperty.value() | ||
HashMap<String, String> enumToPropertyMap = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's retain order by using LinkedHashMap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍🏻
for (AnnotatedField field : annotatedClass.fields()) { | ||
JsonProperty property = field.getAnnotation(JsonProperty.class); | ||
if (property != null) { | ||
enumToPropertyMap.put(field.getName(), property.value()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check for empty name ("")? If existing code doesn't check, that's fine I guess but I think often happens when just adding @JsonProperty
as-is (useless annotation for Enums of course), or specifying other properties but not value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍🏻 Revised(moved) this check to right before adding it to the Map.
Done, in accordance with your other comment 👍🏻
} | ||
final Class<?> enumType = annotatedClass.getRawType(); | ||
HashMap<String,String> expl = null; | ||
for (Field f : enumType.getDeclaredFields()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why iterate over these again? Didn't AnnotatedClass.fields()
have everything we need?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you are right about that AnnotatedClass.fields()
does and "should" have everything we need. This one was from previous implementation and no longer needed.
Removed this whole iteration starting from....
final Class<?> enumType = annotatedClass.getRawType();
..... here ✌🏼
continue; | ||
} | ||
String n = enumToPropertyMap.get(f.getName()); | ||
if (n == null || n.isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok, so empty String is handled here. Could have just not added it in Map earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍🏻 Revised(moved) this check to right before adding it to the Map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, added a minor comment. Hoping to approve and merge tomorrow. Phew!
Thanks, 😆👍🏻 I applied all your comments (became much cleaner) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thank you again for the thorough and solid insightful reviews, @cowtowncoder! FYI, I plan on looking around in the project where we can leverage the new Plz let me know if you need a hand merging this PR into |
@JooHyukKim Agreed. I need to know merge 2.16->master, but I did mark old methods as deprecated and ideally should retrofit methods that call it to avoid them wherever possible. |
@JooHyukKim Was able to merge it. Noticed one other follow-up item: AnnotationIntrospector.findDefaultEnumValue() also takes But I guess it's not a big deal at this point. |
I wrote an issue #3990 to keep more PRs in one place 👍🏻. Will add this one also. |
Motivation
This PR provides more information to
AnnotationIntrospector
forEnum
introspection by passing inMapperConfig
andAnnotatedClass
.Prior to this PR,
Enum
s have been directly handled from class declaration itself, usingClass.getDeclaredFields()
(🔗 check link for reference). Old way of handlingEnum
s not only creates isolation from Jackson's rich functionality, but also down to the kind of basic functionalities such as simple mix-ins which created issues such as #2787.Modifications
AnnotatedFieldCollector
: consider enums as fields.BasicSerializerFactory
: Remove enum self-rerence when handled viaJsonFormat.Shape.Object
BasicDeserializerFactory
: Pass in more information for EnumResolver constructionOriginal PR message (just for reference)