Skip to content

Commit 0cce1ca

Browse files
committed
Fix #1371: add MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
1 parent 2684f15 commit 0cce1ca

File tree

7 files changed

+240
-175
lines changed

7 files changed

+240
-175
lines changed

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Project: jackson-databind
1010
(contributed by Connor K)
1111
#1369: Improve `@JsonCreator` detection via `AnnotationIntrospector`
1212
by passing `MappingConfig`
13+
#1371: Add `MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES` to allow
14+
disabling use of `@CreatorProperties` as explicit `@JsonCreator` equivalent
1315

1416
2.8.3 (not yet released)
1517

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

+106-75
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public enum MapperFeature implements ConfigFeature
1818
{
1919
/*
2020
/******************************************************
21-
/* Introspection features
21+
/* General introspection features
2222
/******************************************************
2323
*/
2424

@@ -32,6 +32,43 @@ public enum MapperFeature implements ConfigFeature
3232
*/
3333
USE_ANNOTATIONS(true),
3434

35+
/**
36+
* Feature that determines whether otherwise regular "getter"
37+
* methods (but only ones that handle Collections and Maps,
38+
* not getters of other type)
39+
* can be used for purpose of getting a reference to a Collection
40+
* and Map to modify the property, without requiring a setter
41+
* method.
42+
* This is similar to how JAXB framework sets Collections and
43+
* Maps: no setter is involved, just setter.
44+
*<p>
45+
* Note that such getters-as-setters methods have lower
46+
* precedence than setters, so they are only used if no
47+
* setter is found for the Map/Collection property.
48+
*<p>
49+
* Feature is enabled by default.
50+
*/
51+
USE_GETTERS_AS_SETTERS(true),
52+
53+
/**
54+
* Feature that determines how <code>transient</code> modifier for fields
55+
* is handled: if disabled, it is only taken to mean exclusion of the field
56+
* as accessor; if true, it is taken to imply removal of the whole property.
57+
*<p>
58+
* Feature is disabled by default, meaning that existence of `transient`
59+
* for a field does not necessarily lead to ignoral of getters or setters
60+
* but just ignoring the use of field for access.
61+
*
62+
* @since 2.6
63+
*/
64+
PROPAGATE_TRANSIENT_MARKER(false),
65+
66+
/*
67+
/******************************************************
68+
/* Introspection-based property auto-detection
69+
/******************************************************
70+
*/
71+
3572
/**
3673
* Feature that determines whether "creator" methods are
3774
* automatically detected by consider public constructors,
@@ -61,7 +98,7 @@ public enum MapperFeature implements ConfigFeature
6198
*<p>
6299
* Feature is enabled by default.
63100
*/
64-
AUTO_DETECT_FIELDS(true),
101+
AUTO_DETECT_FIELDS(true),
65102

66103
/**
67104
* Feature that determines whether regular "getter" methods are
@@ -98,22 +135,22 @@ public enum MapperFeature implements ConfigFeature
98135
*/
99136
AUTO_DETECT_IS_GETTERS(true),
100137

101-
/**
102-
* Feature that determines whether "setter" methods are
103-
* automatically detected based on standard Bean naming convention
104-
* or not. If yes, then all public one-argument methods that
105-
* start with prefix "set"
106-
* are considered setters. If disabled, only methods explicitly
107-
* annotated are considered setters.
108-
*<p>
109-
* Note that this feature has lower precedence than per-class
110-
* annotations, and is only used if there isn't more granular
111-
* configuration available.
112-
*<P>
113-
* Feature is enabled by default.
114-
*/
115-
AUTO_DETECT_SETTERS(true),
116-
138+
/**
139+
* Feature that determines whether "setter" methods are
140+
* automatically detected based on standard Bean naming convention
141+
* or not. If yes, then all public one-argument methods that
142+
* start with prefix "set"
143+
* are considered setters. If disabled, only methods explicitly
144+
* annotated are considered setters.
145+
*<p>
146+
* Note that this feature has lower precedence than per-class
147+
* annotations, and is only used if there isn't more granular
148+
* configuration available.
149+
*<P>
150+
* Feature is enabled by default.
151+
*/
152+
AUTO_DETECT_SETTERS(true),
153+
117154
/**
118155
* Feature that determines whether getters (getter methods)
119156
* can be auto-detected if there is no matching mutator (setter,
@@ -126,22 +163,61 @@ public enum MapperFeature implements ConfigFeature
126163
REQUIRE_SETTERS_FOR_GETTERS(false),
127164

128165
/**
129-
* Feature that determines whether otherwise regular "getter"
130-
* methods (but only ones that handle Collections and Maps,
131-
* not getters of other type)
132-
* can be used for purpose of getting a reference to a Collection
133-
* and Map to modify the property, without requiring a setter
134-
* method.
135-
* This is similar to how JAXB framework sets Collections and
136-
* Maps: no setter is involved, just setter.
166+
* Feature that determines whether member fields declared as 'final' may
167+
* be auto-detected to be used mutators (used to change value of the logical
168+
* property) or not. If enabled, 'final' access modifier has no effect, and
169+
* such fields may be detected according to usual visibility and inference
170+
* rules; if disabled, such fields are NOT used as mutators except if
171+
* explicitly annotated for such use.
137172
*<p>
138-
* Note that such getters-as-setters methods have lower
139-
* precedence than setters, so they are only used if no
140-
* setter is found for the Map/Collection property.
173+
* Feature is enabled by default, for backwards compatibility reasons.
174+
*
175+
* @since 2.2
176+
*/
177+
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
178+
179+
/**
180+
* Feature that determines whether member mutators (fields and
181+
* setters) may be "pulled in" even if they are not visible,
182+
* as long as there is a visible accessor (getter or field) with same name.
183+
* For example: field "value" may be inferred as mutator,
184+
* if there is visible or explicitly marked getter "getValue()".
185+
* If enabled, inferring is enabled; otherwise (disabled) only visible and
186+
* explicitly annotated accessors are ever used.
187+
*<p>
188+
* Note that 'getters' are never inferred and need to be either visible (including
189+
* bean-style naming) or explicitly annotated.
141190
*<p>
142191
* Feature is enabled by default.
192+
*
193+
* @since 2.2
194+
*/
195+
INFER_PROPERTY_MUTATORS(true),
196+
197+
/**
198+
* Feature that determines handling of <code>java.beans.ConstructorProperties<code>
199+
* annotation: when enabled, it is considered as alias of
200+
* {@link com.fasterxml.jackson.annotation.JsonCreator}, to mean that constructor
201+
* should be considered a property-based Creator; when disabled, only constructor
202+
* parameter name information is used, but constructor is NOT considered an explicit
203+
* Creator (although may be discovered as one using other annotations or heuristics).
204+
*<p>
205+
* Feature is mostly used to help interoperability with frameworks like Lombok
206+
* that may automatically generate <code>ConstructorProperties</code> annotation
207+
* but without necessarily meaning that constructor should be used as Creator
208+
* for deserialization.
209+
*<p>
210+
* Feature is enabled by default.
211+
*
212+
* @since 2.7
213+
*/
214+
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),
215+
216+
/*
217+
/******************************************************
218+
/* Access modifier handling
219+
/******************************************************
143220
*/
144-
USE_GETTERS_AS_SETTERS(true),
145221

146222
/**
147223
* Feature that determines whether method and field access
@@ -187,51 +263,6 @@ public enum MapperFeature implements ConfigFeature
187263
*/
188264
OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true),
189265

190-
/**
191-
* Feature that determines whether member mutators (fields and
192-
* setters) may be "pulled in" even if they are not visible,
193-
* as long as there is a visible accessor (getter or field) with same name.
194-
* For example: field "value" may be inferred as mutator,
195-
* if there is visible or explicitly marked getter "getValue()".
196-
* If enabled, inferring is enabled; otherwise (disabled) only visible and
197-
* explicitly annotated accessors are ever used.
198-
*<p>
199-
* Note that 'getters' are never inferred and need to be either visible (including
200-
* bean-style naming) or explicitly annotated.
201-
*<p>
202-
* Feature is enabled by default.
203-
*
204-
* @since 2.2
205-
*/
206-
INFER_PROPERTY_MUTATORS(true),
207-
208-
/**
209-
* Feature that determines whether member fields declared as 'final' may
210-
* be auto-detected to be used mutators (used to change value of the logical
211-
* property) or not. If enabled, 'final' access modifier has no effect, and
212-
* such fields may be detected according to usual visibility and inference
213-
* rules; if disabled, such fields are NOT used as mutators except if
214-
* explicitly annotated for such use.
215-
*<p>
216-
* Feature is enabled by default, for backwards compatibility reasons.
217-
*
218-
* @since 2.2
219-
*/
220-
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
221-
222-
/**
223-
* Feature that determines how <code>transient</code> modifier for fields
224-
* is handled: if disabled, it is only taken to mean exclusion of the field
225-
* as accessor; if true, removal of the whole property.
226-
*<p>
227-
* Feature is disabled by default, meaning that existence of `transient`
228-
* for a field does not necessarily lead to ignoral of getters or setters
229-
* but just ignoring the use of field for access.
230-
*
231-
* @since 2.6
232-
*/
233-
PROPAGATE_TRANSIENT_MARKER(false),
234-
235266
/*
236267
/******************************************************
237268
/* Type-handling features

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1142,14 +1142,14 @@ public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated
11421142
}
11431143

11441144
if (_cfgConstructorPropertiesImpliesCreator
1145-
// && config.isEnabled(MapperFeature.))
1145+
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
11461146
) {
11471147
if (a instanceof AnnotatedConstructor) {
11481148
if (_java7Helper != null) {
11491149
Boolean b = _java7Helper.hasCreatorAnnotation(a);
11501150
if ((b != null) && b.booleanValue()) {
1151-
// 13-Sep-2016, tatu: Judgment call, but I don't JDK ever intended use
1152-
// of delegate, but assumed as-properties implicitly
1151+
// 13-Sep-2016, tatu: Judgment call, but I don't think JDK ever implies
1152+
// use of delegate; assumes as-properties implicitly
11531153
return JsonCreator.Mode.PROPERTIES;
11541154
}
11551155
}

src/main/java/com/fasterxml/jackson/databind/jsontype/TypeSerializer.java

+23-23
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ public abstract class TypeSerializer
7373
*
7474
* @param value Value that will be serialized, for which type information is
7575
* to be written
76-
* @param jgen Generator to use for writing type information
76+
* @param g Generator to use for writing type information
7777
*/
78-
public abstract void writeTypePrefixForScalar(Object value, JsonGenerator jgen) throws IOException;
78+
public abstract void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException;
7979

8080
/**
8181
* Method called to write initial part of type information for given
@@ -86,9 +86,9 @@ public abstract class TypeSerializer
8686
*
8787
* @param value Value that will be serialized, for which type information is
8888
* to be written
89-
* @param jgen Generator to use for writing type information
89+
* @param g Generator to use for writing type information
9090
*/
91-
public abstract void writeTypePrefixForObject(Object value, JsonGenerator jgen) throws IOException;
91+
public abstract void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException;
9292

9393
/**
9494
* Method called to write initial part of type information for given
@@ -99,59 +99,59 @@ public abstract class TypeSerializer
9999
*
100100
* @param value Value that will be serialized, for which type information is
101101
* to be written
102-
* @param jgen Generator to use for writing type information
102+
* @param g Generator to use for writing type information
103103
*/
104-
public abstract void writeTypePrefixForArray(Object value, JsonGenerator jgen) throws IOException;
104+
public abstract void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException;
105105

106106
/**
107107
* Method called after value has been serialized, to close any scopes opened
108108
* by earlier matching call to {@link #writeTypePrefixForScalar}.
109109
* Actual action to take may depend on various factors, but has to match with
110110
* action {@link #writeTypePrefixForScalar} did (close array or object; or do nothing).
111111
*/
112-
public abstract void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) throws IOException;
112+
public abstract void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException;
113113

114114
/**
115115
* Method called after value has been serialized, to close any scopes opened
116116
* by earlier matching call to {@link #writeTypePrefixForObject}.
117117
* It needs to write closing END_OBJECT marker, and any other decoration
118118
* that needs to be matched.
119119
*/
120-
public abstract void writeTypeSuffixForObject(Object value, JsonGenerator jgen) throws IOException;
120+
public abstract void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException;
121121

122122
/**
123123
* Method called after value has been serialized, to close any scopes opened
124124
* by earlier matching call to {@link #writeTypeSuffixForScalar}.
125125
* It needs to write closing END_ARRAY marker, and any other decoration
126126
* that needs to be matched.
127127
*/
128-
public abstract void writeTypeSuffixForArray(Object value, JsonGenerator jgen) throws IOException;
128+
public abstract void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException;
129129

130130
/**
131131
* Alternative version of the prefix-for-scalar method, which is given
132132
* actual type to use (instead of using exact type of the value); typically
133133
* a super type of actual value type
134134
*/
135-
public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
136-
writeTypePrefixForScalar(value, jgen);
135+
public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type) throws IOException {
136+
writeTypePrefixForScalar(value, g);
137137
}
138138

139139
/**
140140
* Alternative version of the prefix-for-object method, which is given
141141
* actual type to use (instead of using exact type of the value); typically
142142
* a super type of actual value type
143143
*/
144-
public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
145-
writeTypePrefixForObject(value, jgen);
144+
public void writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type) throws IOException {
145+
writeTypePrefixForObject(value, g);
146146
}
147147

148148
/**
149149
* Alternative version of the prefix-for-array method, which is given
150150
* actual type to use (instead of using exact type of the value); typically
151151
* a super type of actual value type
152152
*/
153-
public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> type) throws IOException {
154-
writeTypePrefixForArray(value, jgen);
153+
public void writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type) throws IOException {
154+
writeTypePrefixForArray(value, g);
155155
}
156156

157157
/*
@@ -170,10 +170,10 @@ public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> t
170170
*
171171
* @param value Value that will be serialized, for which type information is
172172
* to be written
173-
* @param jgen Generator to use for writing type information
173+
* @param g Generator to use for writing type information
174174
* @param typeId Exact type id to use
175175
*/
176-
public abstract void writeCustomTypePrefixForScalar(Object value, JsonGenerator jgen, String typeId) throws IOException, JsonProcessingException;
176+
public abstract void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException, JsonProcessingException;
177177

178178
/**
179179
* Method called to write initial part of type information for given
@@ -185,16 +185,16 @@ public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> t
185185
*
186186
* @param value Value that will be serialized, for which type information is
187187
* to be written
188-
* @param jgen Generator to use for writing type information
188+
* @param g Generator to use for writing type information
189189
* @param typeId Exact type id to use
190190
*/
191-
public abstract void writeCustomTypePrefixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException;
191+
public abstract void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException;
192192

193-
public abstract void writeCustomTypePrefixForArray(Object value, JsonGenerator jgen, String typeId) throws IOException;
193+
public abstract void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException;
194194

195-
public abstract void writeCustomTypeSuffixForScalar(Object value, JsonGenerator jgen, String typeId) throws IOException;
195+
public abstract void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException;
196196

197-
public abstract void writeCustomTypeSuffixForObject(Object value, JsonGenerator jgen, String typeId) throws IOException;
197+
public abstract void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException;
198198

199-
public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator jgen, String typeId) throws IOException;
199+
public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException;
200200
}

0 commit comments

Comments
 (0)