Skip to content

Commit

Permalink
Fix #1371: add MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Sep 15, 2016
1 parent 2684f15 commit 0cce1ca
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 175 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Project: jackson-databind
(contributed by Connor K)
#1369: Improve `@JsonCreator` detection via `AnnotationIntrospector`
by passing `MappingConfig`
#1371: Add `MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES` to allow
disabling use of `@CreatorProperties` as explicit `@JsonCreator` equivalent

2.8.3 (not yet released)

Expand Down
181 changes: 106 additions & 75 deletions src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum MapperFeature implements ConfigFeature
{
/*
/******************************************************
/* Introspection features
/* General introspection features
/******************************************************
*/

Expand All @@ -32,6 +32,43 @@ public enum MapperFeature implements ConfigFeature
*/
USE_ANNOTATIONS(true),

/**
* Feature that determines whether otherwise regular "getter"
* methods (but only ones that handle Collections and Maps,
* not getters of other type)
* can be used for purpose of getting a reference to a Collection
* and Map to modify the property, without requiring a setter
* method.
* This is similar to how JAXB framework sets Collections and
* Maps: no setter is involved, just setter.
*<p>
* Note that such getters-as-setters methods have lower
* precedence than setters, so they are only used if no
* setter is found for the Map/Collection property.
*<p>
* Feature is enabled by default.
*/
USE_GETTERS_AS_SETTERS(true),

/**
* Feature that determines how <code>transient</code> modifier for fields
* is handled: if disabled, it is only taken to mean exclusion of the field
* as accessor; if true, it is taken to imply removal of the whole property.
*<p>
* Feature is disabled by default, meaning that existence of `transient`
* for a field does not necessarily lead to ignoral of getters or setters
* but just ignoring the use of field for access.
*
* @since 2.6
*/
PROPAGATE_TRANSIENT_MARKER(false),

/*
/******************************************************
/* Introspection-based property auto-detection
/******************************************************
*/

/**
* Feature that determines whether "creator" methods are
* automatically detected by consider public constructors,
Expand Down Expand Up @@ -61,7 +98,7 @@ public enum MapperFeature implements ConfigFeature
*<p>
* Feature is enabled by default.
*/
AUTO_DETECT_FIELDS(true),
AUTO_DETECT_FIELDS(true),

/**
* Feature that determines whether regular "getter" methods are
Expand Down Expand Up @@ -98,22 +135,22 @@ public enum MapperFeature implements ConfigFeature
*/
AUTO_DETECT_IS_GETTERS(true),

/**
* Feature that determines whether "setter" methods are
* automatically detected based on standard Bean naming convention
* or not. If yes, then all public one-argument methods that
* start with prefix "set"
* are considered setters. If disabled, only methods explicitly
* annotated are considered setters.
*<p>
* Note that this feature has lower precedence than per-class
* annotations, and is only used if there isn't more granular
* configuration available.
*<P>
* Feature is enabled by default.
*/
AUTO_DETECT_SETTERS(true),
/**
* Feature that determines whether "setter" methods are
* automatically detected based on standard Bean naming convention
* or not. If yes, then all public one-argument methods that
* start with prefix "set"
* are considered setters. If disabled, only methods explicitly
* annotated are considered setters.
*<p>
* Note that this feature has lower precedence than per-class
* annotations, and is only used if there isn't more granular
* configuration available.
*<P>
* Feature is enabled by default.
*/
AUTO_DETECT_SETTERS(true),

/**
* Feature that determines whether getters (getter methods)
* can be auto-detected if there is no matching mutator (setter,
Expand All @@ -126,22 +163,61 @@ public enum MapperFeature implements ConfigFeature
REQUIRE_SETTERS_FOR_GETTERS(false),

/**
* Feature that determines whether otherwise regular "getter"
* methods (but only ones that handle Collections and Maps,
* not getters of other type)
* can be used for purpose of getting a reference to a Collection
* and Map to modify the property, without requiring a setter
* method.
* This is similar to how JAXB framework sets Collections and
* Maps: no setter is involved, just setter.
* Feature that determines whether member fields declared as 'final' may
* be auto-detected to be used mutators (used to change value of the logical
* property) or not. If enabled, 'final' access modifier has no effect, and
* such fields may be detected according to usual visibility and inference
* rules; if disabled, such fields are NOT used as mutators except if
* explicitly annotated for such use.
*<p>
* Note that such getters-as-setters methods have lower
* precedence than setters, so they are only used if no
* setter is found for the Map/Collection property.
* Feature is enabled by default, for backwards compatibility reasons.
*
* @since 2.2
*/
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),

/**
* Feature that determines whether member mutators (fields and
* setters) may be "pulled in" even if they are not visible,
* as long as there is a visible accessor (getter or field) with same name.
* For example: field "value" may be inferred as mutator,
* if there is visible or explicitly marked getter "getValue()".
* If enabled, inferring is enabled; otherwise (disabled) only visible and
* explicitly annotated accessors are ever used.
*<p>
* Note that 'getters' are never inferred and need to be either visible (including
* bean-style naming) or explicitly annotated.
*<p>
* Feature is enabled by default.
*
* @since 2.2
*/
INFER_PROPERTY_MUTATORS(true),

/**
* Feature that determines handling of <code>java.beans.ConstructorProperties<code>
* annotation: when enabled, it is considered as alias of
* {@link com.fasterxml.jackson.annotation.JsonCreator}, to mean that constructor
* should be considered a property-based Creator; when disabled, only constructor
* parameter name information is used, but constructor is NOT considered an explicit
* Creator (although may be discovered as one using other annotations or heuristics).
*<p>
* Feature is mostly used to help interoperability with frameworks like Lombok
* that may automatically generate <code>ConstructorProperties</code> annotation
* but without necessarily meaning that constructor should be used as Creator
* for deserialization.
*<p>
* Feature is enabled by default.
*
* @since 2.7
*/
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),

/*
/******************************************************
/* Access modifier handling
/******************************************************
*/
USE_GETTERS_AS_SETTERS(true),

/**
* Feature that determines whether method and field access
Expand Down Expand Up @@ -187,51 +263,6 @@ public enum MapperFeature implements ConfigFeature
*/
OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true),

/**
* Feature that determines whether member mutators (fields and
* setters) may be "pulled in" even if they are not visible,
* as long as there is a visible accessor (getter or field) with same name.
* For example: field "value" may be inferred as mutator,
* if there is visible or explicitly marked getter "getValue()".
* If enabled, inferring is enabled; otherwise (disabled) only visible and
* explicitly annotated accessors are ever used.
*<p>
* Note that 'getters' are never inferred and need to be either visible (including
* bean-style naming) or explicitly annotated.
*<p>
* Feature is enabled by default.
*
* @since 2.2
*/
INFER_PROPERTY_MUTATORS(true),

/**
* Feature that determines whether member fields declared as 'final' may
* be auto-detected to be used mutators (used to change value of the logical
* property) or not. If enabled, 'final' access modifier has no effect, and
* such fields may be detected according to usual visibility and inference
* rules; if disabled, such fields are NOT used as mutators except if
* explicitly annotated for such use.
*<p>
* Feature is enabled by default, for backwards compatibility reasons.
*
* @since 2.2
*/
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),

/**
* Feature that determines how <code>transient</code> modifier for fields
* is handled: if disabled, it is only taken to mean exclusion of the field
* as accessor; if true, removal of the whole property.
*<p>
* Feature is disabled by default, meaning that existence of `transient`
* for a field does not necessarily lead to ignoral of getters or setters
* but just ignoring the use of field for access.
*
* @since 2.6
*/
PROPAGATE_TRANSIENT_MARKER(false),

/*
/******************************************************
/* Type-handling features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1142,14 +1142,14 @@ public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated
}

if (_cfgConstructorPropertiesImpliesCreator
// && config.isEnabled(MapperFeature.))
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
) {
if (a instanceof AnnotatedConstructor) {
if (_java7Helper != null) {
Boolean b = _java7Helper.hasCreatorAnnotation(a);
if ((b != null) && b.booleanValue()) {
// 13-Sep-2016, tatu: Judgment call, but I don't JDK ever intended use
// of delegate, but assumed as-properties implicitly
// 13-Sep-2016, tatu: Judgment call, but I don't think JDK ever implies
// use of delegate; assumes as-properties implicitly
return JsonCreator.Mode.PROPERTIES;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ public abstract class TypeSerializer
*
* @param value Value that will be serialized, for which type information is
* to be written
* @param jgen Generator to use for writing type information
* @param g Generator to use for writing type information
*/
public abstract void writeTypePrefixForScalar(Object value, JsonGenerator jgen) throws IOException;
public abstract void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException;

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

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

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

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

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

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

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

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

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

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

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

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

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

public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator jgen, String typeId) throws IOException;
public abstract void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException;
}
Loading

0 comments on commit 0cce1ca

Please sign in to comment.