Skip to content

Commit a83b73f

Browse files
committed
Fixed #1852
1 parent b28ffa2 commit a83b73f

File tree

4 files changed

+71
-15
lines changed

4 files changed

+71
-15
lines changed

release-notes/CREDITS-2.x

+5
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,11 @@ Mike Gilbode (gilbode@github)
11381138
* Reported #792: Deserialization Not Working Right with Generic Types and Builders
11391139
(2.12.0)
11401140
1141+
Patrick Jungermann (pjungermann@github)
1142+
* Requested #1852: Allow case insensitive deserialization of String value into
1143+
`boolean`/`Boolean` (esp for Excel)
1144+
(2.12.0)
1145+
11411146
Nate Bauernfeind (nbauernfeind@github)
11421147
* Reported #2091: `ReferenceType` does not expose valid containedType
11431148
(2.12.0)

release-notes/VERSION-2.x

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Project: jackson-databind
88

99
#921: Deserialization Not Working Right with Generic Types and Builders
1010
(reported by Mike G; fix contributed by Ville K)
11+
#1852: Allow case insensitive deserialization of String value into
12+
`boolean`/`Boolean` (esp for Excel)
13+
(requested by Patrick J)
1114
#1886: Allow use of `@JsonFormat(with=JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)`
1215
on Class
1316
#1919: Abstract class included as part of known type ids for error message

src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java

+48-14
Original file line numberDiff line numberDiff line change
@@ -398,20 +398,25 @@ protected final boolean _parseBooleanPrimitive(JsonParser p, DeserializationCont
398398
return false;
399399
}
400400
text = text.trim();
401-
// [databind#422]: Allow aliases
402-
// 13-Jun-2020, tatu: ... should we consider "lenient" vs "strict" here?
403-
if ("true".equals(text) || "True".equals(text)) {
404-
return true;
405-
}
406-
if ("false".equals(text) || "False".equals(text)) {
407-
return false;
401+
final int len = text.length();
402+
403+
// For [databind#1852] allow some case-insensitive matches (namely,
404+
// true/True/TRUE, false/False/FALSE
405+
if (len == 4) {
406+
if (_isTrue(text)) {
407+
return true;
408+
}
409+
} else if (len == 5) {
410+
if (_isFalse(text)) {
411+
return false;
412+
}
408413
}
409414
if (_hasTextualNull(text)) {
410415
_verifyNullForPrimitiveCoercion(ctxt, text);
411416
return false;
412417
}
413418
Boolean b = (Boolean) ctxt.handleWeirdStringValue(Boolean.TYPE, text,
414-
"only \"true\" or \"false\" recognized");
419+
"only \"true\"/\"True\"/\"TRUE\" or \"false\"/\"False\"/\"FALSE\" recognized");
415420
return Boolean.TRUE.equals(b);
416421
}
417422
// 12-Jun-2020, tatu: For some reason calling `_deserializeFromArray()` won't work so:
@@ -424,6 +429,29 @@ protected final boolean _parseBooleanPrimitive(JsonParser p, DeserializationCont
424429
return ((Boolean) ctxt.handleUnexpectedToken(Boolean.TYPE, p)).booleanValue();
425430
}
426431

432+
// [databind#1852]
433+
protected boolean _isTrue(String text) {
434+
char c = text.charAt(0);
435+
if (c == 't') {
436+
return "true".equals(text);
437+
}
438+
if (c == 'T') {
439+
return "TRUE".equals(text) || "True".equals(text);
440+
}
441+
return false;
442+
}
443+
444+
protected boolean _isFalse(String text) {
445+
char c = text.charAt(0);
446+
if (c == 'f') {
447+
return "false".equals(text);
448+
}
449+
if (c == 'F') {
450+
return "FALSE".equals(text) || "False".equals(text);
451+
}
452+
return false;
453+
}
454+
427455
/**
428456
* Helper method called for cases where non-primitive, boolean-based value
429457
* is to be deserialized: result of this method will be {@link java.lang.Boolean},
@@ -458,12 +486,18 @@ protected final Boolean _parseBoolean(JsonParser p, DeserializationContext ctxt,
458486
return false;
459487
}
460488
text = text.trim();
461-
// [databind#422]: Allow aliases
462-
if ("true".equals(text) || "True".equals(text)) {
463-
return true;
464-
}
465-
if ("false".equals(text) || "False".equals(text)) {
466-
return false;
489+
final int len = text.length();
490+
491+
// For [databind#1852] allow some case-insensitive matches (namely,
492+
// true/True/TRUE, false/False/FALSE
493+
if (len == 4) {
494+
if (_isTrue(text)) {
495+
return true;
496+
}
497+
} else if (len == 5) {
498+
if (_isFalse(text)) {
499+
return false;
500+
}
467501
}
468502
if (_checkTextualNull(ctxt, text)) {
469503
return null;

src/test/java/com/fasterxml/jackson/databind/convert/CoerceJDKScalarsTest.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private void _verifyNullFail(Class<?> type) throws IOException
113113
/**********************************************************
114114
*/
115115

116-
public void testStringCoercionOk() throws Exception
116+
public void testStringCoercionOkBoolean() throws Exception
117117
{
118118
// first successful coercions. Boolean has a ton...
119119
_verifyCoerceSuccess("1", Boolean.TYPE, Boolean.TRUE);
@@ -122,13 +122,20 @@ public void testStringCoercionOk() throws Exception
122122
_verifyCoerceSuccess(quote("true"), Boolean.class, Boolean.TRUE);
123123
_verifyCoerceSuccess(quote("True"), Boolean.TYPE, Boolean.TRUE);
124124
_verifyCoerceSuccess(quote("True"), Boolean.class, Boolean.TRUE);
125+
_verifyCoerceSuccess(quote("TRUE"), Boolean.TYPE, Boolean.TRUE);
126+
_verifyCoerceSuccess(quote("TRUE"), Boolean.class, Boolean.TRUE);
125127
_verifyCoerceSuccess("0", Boolean.TYPE, Boolean.FALSE);
126128
_verifyCoerceSuccess("0", Boolean.class, Boolean.FALSE);
127129
_verifyCoerceSuccess(quote("false"), Boolean.TYPE, Boolean.FALSE);
128130
_verifyCoerceSuccess(quote("false"), Boolean.class, Boolean.FALSE);
129131
_verifyCoerceSuccess(quote("False"), Boolean.TYPE, Boolean.FALSE);
130132
_verifyCoerceSuccess(quote("False"), Boolean.class, Boolean.FALSE);
133+
_verifyCoerceSuccess(quote("FALSE"), Boolean.TYPE, Boolean.FALSE);
134+
_verifyCoerceSuccess(quote("FALSE"), Boolean.class, Boolean.FALSE);
135+
}
131136

137+
public void testStringCoercionOkNumbers() throws Exception
138+
{
132139
_verifyCoerceSuccess(quote("123"), Byte.TYPE, Byte.valueOf((byte) 123));
133140
_verifyCoerceSuccess(quote("123"), Byte.class, Byte.valueOf((byte) 123));
134141
_verifyCoerceSuccess(quote("123"), Short.TYPE, Short.valueOf((short) 123));
@@ -154,6 +161,13 @@ public void testStringCoercionFailBoolean() throws Exception
154161
{
155162
_verifyRootStringCoerceFail("true", Boolean.TYPE);
156163
_verifyRootStringCoerceFail("true", Boolean.class);
164+
_verifyRootStringCoerceFail("True", Boolean.TYPE);
165+
_verifyRootStringCoerceFail("True", Boolean.class);
166+
_verifyRootStringCoerceFail("TRUE", Boolean.TYPE);
167+
_verifyRootStringCoerceFail("TRUE", Boolean.class);
168+
169+
_verifyRootStringCoerceFail("false", Boolean.TYPE);
170+
_verifyRootStringCoerceFail("false", Boolean.class);
157171
}
158172

159173
public void testStringCoercionFailInteger() throws Exception

0 commit comments

Comments
 (0)