Skip to content

Commit 54ad6a2

Browse files
authored
Fix #4364: add PropertyName.merge(), use by AnnotationIntrospectorPair (#4365)
1 parent 1882542 commit 54ad6a2

File tree

5 files changed

+87
-102
lines changed

5 files changed

+87
-102
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Project: jackson-databind
4141
(reported by @k-wall)
4242
(fix contributed by Joo-Hyuk K)
4343
#4337: `AtomicReference` serializer does not support `@JsonSerialize(contentConverter=...)`
44+
#4364: `@JsonProperty` and equivalents should merge with `AnnotationIntrospectorPair`
4445
- JUnit5 upgraded to 5.10.1
4546
4647
2.16.2 (not yet released)

src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java

-29
Original file line numberDiff line numberDiff line change
@@ -412,35 +412,6 @@ public JsonIncludeProperties.Value findPropertyInclusionByName(MapperConfig<?> c
412412
*/
413413
public String findClassDescription(AnnotatedClass ac) { return null; }
414414

415-
/**
416-
* @param forSerialization True if requesting properties to ignore for serialization;
417-
* false if for deserialization
418-
* @param ac Annotated class to introspect
419-
*
420-
* @return Array of names of properties to ignore
421-
*
422-
* @since 2.6
423-
*
424-
* @deprecated Since 2.8, use {@link #findPropertyIgnoralByName} instead
425-
*/
426-
@Deprecated // since 2.8
427-
public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) {
428-
return null;
429-
}
430-
431-
/**
432-
* Method for checking whether an annotation indicates that all unknown properties
433-
* should be ignored.
434-
*
435-
* @param ac Annotated class to introspect
436-
*
437-
* @return True if class has something indicating "ignore [all] unknown properties"
438-
*
439-
* @deprecated Since 2.8, use {@link #findPropertyIgnoralByName} instead
440-
*/
441-
@Deprecated // since 2.8
442-
public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { return null; }
443-
444415
/**
445416
* @param ac Annotated class to introspect
446417
*

src/main/java/com/fasterxml/jackson/databind/PropertyName.java

+49-4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,51 @@ public static PropertyName construct(String simpleName, String ns)
108108
return new PropertyName(InternCache.instance.intern(simpleName), ns);
109109
}
110110

111+
/**
112+
* Method that will combine information from two {@link PropertyName}
113+
* instances
114+
*
115+
* @param name1 Name with higher precedence; may be {@code null}
116+
* @param name2 Name with lower precedence; may be {@code null}
117+
*
118+
* @return Merged information; only {@code null} if both arguments
119+
* are {@code null}s.
120+
*
121+
* @since 2.17
122+
*/
123+
public static PropertyName merge(PropertyName name1, PropertyName name2) {
124+
if (name1 == null) {
125+
return name2;
126+
}
127+
if (name2 == null) {
128+
return name1;
129+
}
130+
String ns = _nonEmpty(name1._namespace, name2._namespace);
131+
String simple = _nonEmpty(name1._simpleName, name2._simpleName);
132+
133+
// But see if we can just return one of arguments as-is:
134+
if (ns == name1._namespace && simple == name1._simpleName) {
135+
return name1;
136+
}
137+
if (ns == name2._namespace && simple == name2._simpleName) {
138+
return name2;
139+
}
140+
return construct(simple, ns);
141+
}
142+
143+
private static String _nonEmpty(String str1, String str2) {
144+
if (str1 == null) {
145+
return str2;
146+
}
147+
if (str2 == null) {
148+
return str1;
149+
}
150+
if (str1.isEmpty()) {
151+
return str2;
152+
}
153+
return str1;
154+
}
155+
111156
public PropertyName internSimpleName()
112157
{
113158
if (_simpleName.isEmpty()) { // empty String is canonical already
@@ -222,9 +267,8 @@ public boolean equals(Object o)
222267
{
223268
if (o == this) return true;
224269
if (o == null) return false;
225-
/* 13-Nov-2012, tatu: by default, require strict type equality.
226-
* Re-evaluate if this becomes an issue.
227-
*/
270+
// 13-Nov-2012, tatu: by default, require strict type equality.
271+
// Re-evaluate if this becomes an issue.
228272
if (o.getClass() != getClass()) return false;
229273
// 13-Nov-2012, tatu: Should we have specific rules on matching USE_DEFAULT?
230274
// (like, it only ever matching exact instance)
@@ -244,7 +288,8 @@ public boolean equals(Object o)
244288

245289
@Override
246290
public int hashCode() {
247-
return Objects.hash(_namespace, _simpleName);
291+
return Objects.hashCode(_simpleName) * 31
292+
+ Objects.hashCode(_namespace);
248293
}
249294

250295
@Override

src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java

+11-69
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,8 @@ public boolean isAnnotationBundle(Annotation ann) {
9797
@Override
9898
public PropertyName findRootName(AnnotatedClass ac)
9999
{
100-
PropertyName name1 = _primary.findRootName(ac);
101-
if (name1 == null) {
102-
return _secondary.findRootName(ac);
103-
}
104-
if (name1.hasSimpleName()) {
105-
return name1;
106-
}
107-
// name1 is empty; how about secondary?
108-
PropertyName name2 = _secondary.findRootName(ac);
109-
return (name2 == null) ? name1 : name2;
100+
return PropertyName.merge(_primary.findRootName(ac),
101+
_secondary.findRootName(ac));
110102
}
111103

112104
// since 2.12
@@ -177,27 +169,6 @@ public String findClassDescription(AnnotatedClass ac) {
177169
return str;
178170
}
179171

180-
@Override
181-
@Deprecated // since 2.8
182-
public String[] findPropertiesToIgnore(Annotated ac, boolean forSerialization) {
183-
String[] result = _primary.findPropertiesToIgnore(ac, forSerialization);
184-
if (result == null) {
185-
result = _secondary.findPropertiesToIgnore(ac, forSerialization);
186-
}
187-
return result;
188-
}
189-
190-
@Override
191-
@Deprecated // since 2.8
192-
public Boolean findIgnoreUnknownProperties(AnnotatedClass ac)
193-
{
194-
Boolean result = _primary.findIgnoreUnknownProperties(ac);
195-
if (result == null) {
196-
result = _secondary.findIgnoreUnknownProperties(ac);
197-
}
198-
return result;
199-
}
200-
201172
@Override
202173
@Deprecated // since 2.12
203174
public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a)
@@ -464,17 +435,8 @@ public JsonFormat.Value findFormat(Annotated ann) {
464435

465436
@Override
466437
public PropertyName findWrapperName(Annotated ann) {
467-
PropertyName name = _primary.findWrapperName(ann);
468-
if (name == null) {
469-
name = _secondary.findWrapperName(ann);
470-
} else if (name == PropertyName.USE_DEFAULT) {
471-
// does the other introspector have a better idea?
472-
PropertyName name2 = _secondary.findWrapperName(ann);
473-
if (name2 != null) {
474-
name = name2;
475-
}
476-
}
477-
return name;
438+
return PropertyName.merge(_primary.findWrapperName(ann),
439+
_secondary.findWrapperName(ann));
478440
}
479441

480442
@Override
@@ -534,11 +496,8 @@ public AnnotatedMethod resolveSetterConflict(MapperConfig<?> config,
534496
@Override // since 2.11
535497
public PropertyName findRenameByField(MapperConfig<?> config,
536498
AnnotatedField f, PropertyName implName) {
537-
PropertyName n = _secondary.findRenameByField(config, f, implName);
538-
if (n == null) {
539-
n = _primary.findRenameByField(config, f, implName);
540-
}
541-
return n;
499+
return PropertyName.merge(_secondary.findRenameByField(config, f, implName),
500+
_primary.findRenameByField(config, f, implName));
542501
}
543502

544503
// // // Serialization: type refinements
@@ -577,17 +536,8 @@ public void findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass a
577536

578537
@Override
579538
public PropertyName findNameForSerialization(Annotated a) {
580-
PropertyName n = _primary.findNameForSerialization(a);
581-
// note: "use default" should not block explicit answer, so:
582-
if (n == null) {
583-
n = _secondary.findNameForSerialization(a);
584-
} else if (n == PropertyName.USE_DEFAULT) {
585-
PropertyName n2 = _secondary.findNameForSerialization(a);
586-
if (n2 != null) {
587-
n = n2;
588-
}
589-
}
590-
return n;
539+
return PropertyName.merge(_primary.findNameForSerialization(a),
540+
_secondary.findNameForSerialization(a));
591541
}
592542

593543
@Override
@@ -764,17 +714,9 @@ public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
764714
@Override
765715
public PropertyName findNameForDeserialization(Annotated a)
766716
{
767-
// note: "use default" should not block explicit answer, so:
768-
PropertyName n = _primary.findNameForDeserialization(a);
769-
if (n == null) {
770-
n = _secondary.findNameForDeserialization(a);
771-
} else if (n == PropertyName.USE_DEFAULT) {
772-
PropertyName n2 = _secondary.findNameForDeserialization(a);
773-
if (n2 != null) {
774-
n = n2;
775-
}
776-
}
777-
return n;
717+
return PropertyName.merge(
718+
_primary.findNameForDeserialization(a),
719+
_secondary.findNameForDeserialization(a));
778720
}
779721

780722
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.databind;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertSame;
7+
8+
public class PropertyNameTest
9+
{
10+
@Test
11+
public void testMerging() {
12+
PropertyName name1 = PropertyName.construct("name1", "ns1");
13+
PropertyName name2 = PropertyName.construct("name2", "ns2");
14+
PropertyName empty = PropertyName.construct("", null);
15+
PropertyName nsX = PropertyName.construct("", "nsX");
16+
17+
assertSame(name1, PropertyName.merge(name1, name2));
18+
assertSame(name2, PropertyName.merge(name2, name1));
19+
20+
assertSame(name1, PropertyName.merge(name1, empty));
21+
assertSame(name1, PropertyName.merge(empty, name1));
22+
23+
assertEquals(PropertyName.construct("name1", "nsX"),
24+
PropertyName.merge(nsX, name1));
25+
}
26+
}

0 commit comments

Comments
 (0)