4242 */
4343 public OptBoolean useInput () default OptBoolean .DEFAULT ;
4444
45+ /**
46+ * Whether to throw an exception when the {@code ObjectMapper} does not find
47+ * the value to inject.
48+ *<p>
49+ * Default is {@code OptBoolean.DEFAULT} for backwards-compatibility: in this
50+ * case {@code ObjectMapper} defaults are used (which in turn are same
51+ * as {code OptBoolean.FALSE}).
52+ *
53+ * @return {@link OptBoolean#FALSE} to throw an exception; {@link OptBoolean#TRUE}
54+ * to avoid throwing it; or {@link OptBoolean#DEFAULT} to use configure defaults
55+ * (which are same as {@link OptBoolean#FALSE} for Jackson 2.x)
56+ *
57+ * @since 2.20
58+ */
59+ public OptBoolean optional () default OptBoolean .DEFAULT ;
60+
4561 /*
4662 /**********************************************************
4763 /* Value class used to enclose information, allow for
@@ -63,7 +79,7 @@ public static class Value
6379 {
6480 private static final long serialVersionUID = 1L ;
6581
66- protected final static Value EMPTY = new Value (null , null );
82+ protected final static Value EMPTY = new Value (null , null , null );
6783
6884 /**
6985 * Id to use to access injected value; if `null`, "default" name, derived
@@ -73,9 +89,12 @@ public static class Value
7389
7490 protected final Boolean _useInput ;
7591
76- protected Value (Object id , Boolean useInput ) {
92+ protected final Boolean _optional ;
93+
94+ protected Value (Object id , Boolean useInput , Boolean optional ) {
7795 _id = id ;
7896 _useInput = useInput ;
97+ _optional = optional ;
7998 }
8099
81100 @ Override
@@ -93,25 +112,33 @@ public static Value empty() {
93112 return EMPTY ;
94113 }
95114
115+ @ Deprecated //since 2.20
96116 public static Value construct (Object id , Boolean useInput ) {
117+ return construct (id , useInput , null );
118+ }
119+
120+ /**
121+ * @since 2.20
122+ */
123+ public static Value construct (Object id , Boolean useInput , Boolean optional ) {
97124 if ("" .equals (id )) {
98125 id = null ;
99126 }
100- if (_empty (id , useInput )) {
127+ if (_empty (id , useInput , optional )) {
101128 return EMPTY ;
102129 }
103- return new Value (id , useInput );
130+ return new Value (id , useInput , optional );
104131 }
105132
106133 public static Value from (JacksonInject src ) {
107134 if (src == null ) {
108135 return EMPTY ;
109136 }
110- return construct (src .value (), src .useInput ().asBoolean ());
137+ return construct (src .value (), src .useInput ().asBoolean (), src . optional (). asBoolean () );
111138 }
112139
113140 public static Value forId (Object id ) {
114- return construct (id , null );
141+ return construct (id , null , null );
115142 }
116143
117144 /*
@@ -128,7 +155,7 @@ public Value withId(Object id) {
128155 } else if (id .equals (_id )) {
129156 return this ;
130157 }
131- return new Value (id , _useInput );
158+ return new Value (id , _useInput , _optional );
132159 }
133160
134161 public Value withUseInput (Boolean useInput ) {
@@ -139,7 +166,18 @@ public Value withUseInput(Boolean useInput) {
139166 } else if (useInput .equals (_useInput )) {
140167 return this ;
141168 }
142- return new Value (_id , useInput );
169+ return new Value (_id , useInput , _optional );
170+ }
171+
172+ public Value withOptional (Boolean optional ) {
173+ if (optional == null ) {
174+ if (_optional == null ) {
175+ return this ;
176+ }
177+ } else if (optional .equals (_optional )) {
178+ return this ;
179+ }
180+ return new Value (_id , _useInput , optional );
143181 }
144182
145183 /*
@@ -150,6 +188,7 @@ public Value withUseInput(Boolean useInput) {
150188
151189 public Object getId () { return _id ; }
152190 public Boolean getUseInput () { return _useInput ; }
191+ public Boolean getOptional () { return _optional ; }
153192
154193 public boolean hasId () {
155194 return _id != null ;
@@ -167,8 +206,8 @@ public boolean willUseInput(boolean defaultSetting) {
167206
168207 @ Override
169208 public String toString () {
170- return String .format ("JacksonInject.Value(id=%s,useInput=%s)" ,
171- _id , _useInput );
209+ return String .format ("JacksonInject.Value(id=%s,useInput=%s,optional=%s )" ,
210+ _id , _useInput , _optional );
172211 }
173212
174213 @ Override
@@ -180,6 +219,9 @@ public int hashCode() {
180219 if (_useInput != null ) {
181220 h += _useInput .hashCode ();
182221 }
222+ if (_optional != null ) {
223+ h += _optional .hashCode ();
224+ }
183225 return h ;
184226 }
185227
@@ -189,12 +231,13 @@ public boolean equals(Object o) {
189231 if (o == null ) return false ;
190232 if (o .getClass () == getClass ()) {
191233 Value other = (Value ) o ;
192- if (OptBoolean .equals (_useInput , other ._useInput )) {
193- if (_id == null ) {
194- return other ._id == null ;
195- }
196- return _id .equals (other ._id );
197- }
234+
235+ return (_id == null && other ._id == null
236+ || _id != null && _id .equals (other ._id ))
237+ && (_useInput == null && other ._useInput == null
238+ || _useInput != null && _useInput .equals (other ._useInput ))
239+ && (_optional == null && other ._optional == null
240+ || _optional != null && _optional .equals (other ._optional ));
198241 }
199242 return false ;
200243 }
@@ -205,8 +248,8 @@ public boolean equals(Object o) {
205248 /**********************************************************
206249 */
207250
208- private static boolean _empty (Object id , Boolean useInput ) {
209- return (id == null ) && (useInput == null );
251+ private static boolean _empty (Object id , Boolean useInput , Boolean optional ) {
252+ return (id == null ) && (useInput == null ) && optional == null ;
210253 }
211254 }
212255}
0 commit comments