8
8
9
9
import com .fasterxml .jackson .databind .*;
10
10
import com .fasterxml .jackson .databind .annotation .JacksonStdImpl ;
11
+ import com .fasterxml .jackson .databind .cfg .CoercionAction ;
12
+ import com .fasterxml .jackson .databind .cfg .CoercionInputShape ;
11
13
import com .fasterxml .jackson .databind .deser .SettableBeanProperty ;
12
14
import com .fasterxml .jackson .databind .deser .ValueInstantiator ;
13
15
import com .fasterxml .jackson .databind .introspect .AnnotatedMethod ;
@@ -128,46 +130,38 @@ public LogicalType logicalType() {
128
130
return LogicalType .Enum ;
129
131
}
130
132
133
+ @ Override // since 2.12
134
+ public Object getEmptyValue (DeserializationContext ctxt ) throws JsonMappingException {
135
+ return _enumDefaultValue ;
136
+ }
137
+
131
138
@ Override
132
139
public Object deserialize (JsonParser p , DeserializationContext ctxt ) throws IOException
133
140
{
134
- String text ;
135
- JsonToken curr = p .currentToken ();
136
-
137
141
// Usually should just get string value:
138
142
// 04-Sep-2020, tatu: for 2.11.3 / 2.12.0, removed "FIELD_NAME" as allowed;
139
143
// did not work and gave odd error message.
140
- if (curr == JsonToken .VALUE_STRING ) {
141
- text = p .getText ();
144
+ if (p .hasToken (JsonToken .VALUE_STRING )) {
145
+ return _fromString (p , ctxt , p .getText ());
146
+ }
147
+
142
148
// But let's consider int acceptable as well (if within ordinal range)
143
- } else if (curr == JsonToken .VALUE_NUMBER_INT ) {
144
- // ... unless told not to do that
145
- int index = p .getIntValue ();
146
- if (ctxt .isEnabled (DeserializationFeature .FAIL_ON_NUMBERS_FOR_ENUMS )) {
147
- return ctxt .handleWeirdNumberValue (_enumClass (), index ,
148
- "not allowed to deserialize Enum value out of number: disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow"
149
- );
150
- }
151
- if (index >= 0 && index < _enumsByIndex .length ) {
152
- return _enumsByIndex [index ];
153
- }
154
- if ((_enumDefaultValue != null )
155
- && ctxt .isEnabled (DeserializationFeature .READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE )) {
156
- return _enumDefaultValue ;
157
- }
158
- if (!ctxt .isEnabled (DeserializationFeature .READ_UNKNOWN_ENUM_VALUES_AS_NULL )) {
159
- return ctxt .handleWeirdNumberValue (_enumClass (), index ,
160
- "index value outside legal index range [0..%s]" ,
161
- _enumsByIndex .length -1 );
162
- }
163
- return null ;
164
- } else if (curr == JsonToken .START_OBJECT ) {
165
- // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
166
- text = ctxt .extractScalarFromObject (p , this , _valueClass );
167
- } else {
168
- return _deserializeOther (p , ctxt );
149
+ if (p .hasToken (JsonToken .VALUE_NUMBER_INT )) {
150
+ return _fromInteger (p , ctxt , p .getIntValue ());
169
151
}
170
152
153
+ // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
154
+ if (p .isExpectedStartObjectToken ()) {
155
+ return _fromString (p , ctxt ,
156
+ ctxt .extractScalarFromObject (p , this , _valueClass ));
157
+ }
158
+ return _deserializeOther (p , ctxt );
159
+ }
160
+
161
+ protected Object _fromString (JsonParser p , DeserializationContext ctxt ,
162
+ String text )
163
+ throws IOException
164
+ {
171
165
CompactStringObjectMap lookup = ctxt .isEnabled (DeserializationFeature .READ_ENUMS_USING_TO_STRING )
172
166
? _getToStringLookup (ctxt ) : _lookupByName ;
173
167
Object result = lookup .find (text );
@@ -180,20 +174,81 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
180
174
return result ;
181
175
}
182
176
177
+ protected Object _fromInteger (JsonParser p , DeserializationContext ctxt ,
178
+ int index )
179
+ throws IOException
180
+ {
181
+ final CoercionAction act = ctxt .findCoercionAction (logicalType (), handledType (),
182
+ CoercionInputShape .Integer );
183
+
184
+ // First, check legacy setting for slightly different message
185
+ if (act == CoercionAction .Fail ) {
186
+ if (ctxt .isEnabled (DeserializationFeature .FAIL_ON_NUMBERS_FOR_ENUMS )) {
187
+ return ctxt .handleWeirdNumberValue (_enumClass (), index ,
188
+ "not allowed to deserialize Enum value out of number: disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow"
189
+ );
190
+ }
191
+ // otherwise this will force failure with new setting
192
+ _checkCoercionFail (ctxt , act , handledType (), index ,
193
+ "Integer value (" +index +")" );
194
+ }
195
+ switch (act ) {
196
+ case AsNull :
197
+ return null ;
198
+ case AsEmpty :
199
+ return getEmptyValue (ctxt );
200
+ case TryConvert :
201
+ default :
202
+ }
203
+ if (index >= 0 && index < _enumsByIndex .length ) {
204
+ return _enumsByIndex [index ];
205
+ }
206
+ if ((_enumDefaultValue != null )
207
+ && ctxt .isEnabled (DeserializationFeature .READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE )) {
208
+ return _enumDefaultValue ;
209
+ }
210
+ if (!ctxt .isEnabled (DeserializationFeature .READ_UNKNOWN_ENUM_VALUES_AS_NULL )) {
211
+ return ctxt .handleWeirdNumberValue (_enumClass (), index ,
212
+ "index value outside legal index range [0..%s]" ,
213
+ _enumsByIndex .length -1 );
214
+ }
215
+ return null ;
216
+ }
217
+ /*
218
+ return _checkCoercionFail(ctxt, act, rawTargetType, value,
219
+ "empty String (\"\")");
220
+ */
221
+
183
222
/*
184
223
/**********************************************************
185
224
/* Internal helper methods
186
225
/**********************************************************
187
226
*/
188
227
189
228
private final Object _deserializeAltString (JsonParser p , DeserializationContext ctxt ,
190
- CompactStringObjectMap lookup , String name ) throws IOException
229
+ CompactStringObjectMap lookup , String nameOrig ) throws IOException
191
230
{
192
- name = name .trim ();
193
- if (name .length () == 0 ) {
194
- if (ctxt .isEnabled (DeserializationFeature .ACCEPT_EMPTY_STRING_AS_NULL_OBJECT )) {
231
+ String name = nameOrig .trim ();
232
+ if (name .length () == 0 ) { // empty or blank
233
+ CoercionAction act ;
234
+ if (nameOrig .length () == 0 ) {
235
+ act = _findCoercionFromEmptyString (ctxt );
236
+ act = _checkCoercionFail (ctxt , act , handledType (), nameOrig ,
237
+ "empty String (\" \" )" );
238
+ } else {
239
+ act = _findCoercionFromBlankString (ctxt );
240
+ act = _checkCoercionFail (ctxt , act , handledType (), nameOrig ,
241
+ "blank String (all whitespace)" );
242
+ }
243
+ switch (act ) {
244
+ case AsEmpty :
245
+ case TryConvert :
195
246
return getEmptyValue (ctxt );
247
+ case AsNull :
248
+ default : // Fail already handled earlier
196
249
}
250
+ return null ;
251
+ // if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) {
197
252
} else {
198
253
// [databind#1313]: Case insensitive enum deserialization
199
254
if (Boolean .TRUE .equals (_caseInsensitive )) {
0 commit comments