Skip to content

Commit 272c499

Browse files
authored
Merge branch 'FasterXML:2.x' into feature/databind-1381-inject-only
2 parents bc9d37e + 393fc3d commit 272c499

File tree

13 files changed

+290
-38
lines changed

13 files changed

+290
-38
lines changed

release-notes/VERSION-2.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ Project: jackson-databind
2525
#5151: Add new exception type, `MissingInjectValueException`, to be used
2626
for failed `@JacksonInject`
2727
#5179: Add "current token" info into `MismatchedInputException`
28+
#5192: Record types are broken on Android when using R8
29+
(reported by @HelloOO7)
30+
(fix by @pjfanning)
31+
#5197: Add more informative exception for back-references with `record` type
32+
(fix by Joo-Hyuk K)
2833
- Generate SBOMs [JSTEP-14]
2934
3035
2.19.1 (13-Jun-2025)

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,11 @@ protected void addBackReferenceProperties(DeserializationContext ctxt,
787787
}
788788
}
789789
*/
790+
if (beanDesc.isRecordType()) {
791+
ctxt.reportBadTypeDefinition(beanDesc,
792+
"Cannot add back-reference to a `java.lang.Record` type (property '%s')",
793+
refProp.getName());
794+
}
790795
String refName = refProp.findReferenceName();
791796
builder.addBackReferenceProperty(refName, constructSettableProperty(ctxt,
792797
beanDesc, refProp, refProp.getPrimaryType()));

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,18 @@ public EnumMap<?,?> deserialize(JsonParser p, DeserializationContext ctxt,
308308
if (_skipNullValues) {
309309
continue;
310310
}
311-
value = _nullProvider.getNullValue(ctxt);
311+
value = null;
312312
} else {
313313
value = _deserializeNoNullChecks(p, ctxt);
314314
}
315+
316+
if (value == null) {
317+
value = _nullProvider.getNullValue(ctxt);
318+
319+
if (value == null && _skipNullValues) {
320+
continue;
321+
}
322+
}
315323
} catch (Exception e) {
316324
return wrapAndThrow(ctxt, e, result, keyStr);
317325
}
@@ -400,10 +408,18 @@ public EnumMap<?,?> _deserializeUsingProperties(JsonParser p, DeserializationCon
400408
if (_skipNullValues) {
401409
continue;
402410
}
403-
value = _nullProvider.getNullValue(ctxt);
411+
value = null;
404412
} else {
405413
value = _deserializeNoNullChecks(p, ctxt);
406414
}
415+
416+
if (value == null) {
417+
value = _nullProvider.getNullValue(ctxt);
418+
419+
if (value == null && _skipNullValues) {
420+
continue;
421+
}
422+
}
407423
} catch (Exception e) {
408424
wrapAndThrow(ctxt, e, _containerType.getRawClass(), keyName);
409425
return null;

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,9 @@ public EnumSetDeserializer withResolved(JsonDeserializer<?> deser,
139139
@Override
140140
public boolean isCachable() {
141141
// One caveat: content deserializer should prevent caching
142-
if (_enumType.getValueHandler() != null) {
143-
return false;
144-
}
145-
return true;
142+
return _enumType.getValueHandler() == null;
146143
}
147-
144+
148145
@Override // since 2.12
149146
public LogicalType logicalType() {
150147
return LogicalType.Collection;

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,19 @@ protected final Map<Object,Object> _readAndBind(JsonParser p, DeserializationCon
547547
if (_skipNullValues) {
548548
continue;
549549
}
550-
value = _nullProvider.getNullValue(ctxt);
550+
value = null;
551551
} else {
552552
value = _deserializeNoNullChecks(p, ctxt);
553553
}
554+
555+
if (value == null) {
556+
value = _nullProvider.getNullValue(ctxt);
557+
558+
if (value == null && _skipNullValues) {
559+
continue;
560+
}
561+
}
562+
554563
if (useObjectId) {
555564
referringAccumulator.put(key, value);
556565
} else {
@@ -609,10 +618,19 @@ protected final Map<Object,Object> _readAndBindStringKeyMap(JsonParser p, Deseri
609618
if (_skipNullValues) {
610619
continue;
611620
}
612-
value = _nullProvider.getNullValue(ctxt);
621+
value = null;
613622
} else {
614623
value = _deserializeNoNullChecks(p, ctxt);
615624
}
625+
626+
if (value == null) {
627+
value = _nullProvider.getNullValue(ctxt);
628+
629+
if (value == null && _skipNullValues) {
630+
continue;
631+
}
632+
}
633+
616634
if (useObjectId) {
617635
referringAccumulator.put(key, value);
618636
} else {
@@ -679,10 +697,18 @@ public Map<Object,Object> _deserializeUsingCreator(JsonParser p, Deserialization
679697
if (_skipNullValues) {
680698
continue;
681699
}
682-
value = _nullProvider.getNullValue(ctxt);
700+
value = null;
683701
} else {
684702
value = _deserializeNoNullChecks(p, ctxt);
685703
}
704+
705+
if (value == null) {
706+
value = _nullProvider.getNullValue(ctxt);
707+
708+
if (value == null && _skipNullValues) {
709+
continue;
710+
}
711+
}
686712
} catch (Exception e) {
687713
wrapAndThrow(ctxt, e, _containerType.getRawClass(), key);
688714
return null;
@@ -759,6 +785,15 @@ protected final void _readAndUpdate(JsonParser p, DeserializationContext ctxt,
759785
} else {
760786
value = _deserializeNoNullChecks(p, ctxt);
761787
}
788+
789+
if (value == null) {
790+
value = _nullProvider.getNullValue(ctxt);
791+
792+
if (value == null && _skipNullValues) {
793+
continue;
794+
}
795+
}
796+
762797
if (value != old) {
763798
result.put(key, value);
764799
}
@@ -824,6 +859,15 @@ protected final void _readAndUpdateStringKeyMap(JsonParser p, DeserializationCon
824859
} else {
825860
value = _deserializeNoNullChecks(p, ctxt);
826861
}
862+
863+
if (value == null) {
864+
value = _nullProvider.getNullValue(ctxt);
865+
866+
if (value == null && _skipNullValues) {
867+
continue;
868+
}
869+
}
870+
827871
if (value != old) {
828872
result.put(key, value);
829873
}

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)
201201
Object[] chunk = buffer.resetAndStart();
202202
int ix = 0;
203203
JsonToken t;
204-
final TypeDeserializer typeDeser = _elementTypeDeserializer;
205204

206205
try {
207206
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
@@ -213,10 +212,8 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)
213212
continue;
214213
}
215214
value = _nullProvider.getNullValue(ctxt);
216-
} else if (typeDeser == null) {
217-
value = _elementDeserializer.deserialize(p, ctxt);
218215
} else {
219-
value = _elementDeserializer.deserializeWithType(p, ctxt, typeDeser);
216+
value = _deserializeNoNullChecks(p, ctxt);
220217
}
221218
if (ix >= chunk.length) {
222219
chunk = buffer.appendCompletedChunk(chunk);
@@ -269,7 +266,6 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt,
269266
int ix = intoValue.length;
270267
Object[] chunk = buffer.resetAndStart(intoValue, ix);
271268
JsonToken t;
272-
final TypeDeserializer typeDeser = _elementTypeDeserializer;
273269

274270
try {
275271
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
@@ -280,10 +276,8 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt,
280276
continue;
281277
}
282278
value = _nullProvider.getNullValue(ctxt);
283-
} else if (typeDeser == null) {
284-
value = _elementDeserializer.deserialize(p, ctxt);
285279
} else {
286-
value = _elementDeserializer.deserializeWithType(p, ctxt, typeDeser);
280+
value = _deserializeNoNullChecks(p, ctxt);
287281
}
288282
if (ix >= chunk.length) {
289283
chunk = buffer.appendCompletedChunk(chunk);
@@ -320,7 +314,7 @@ protected Byte[] deserializeFromBase64(JsonParser p, DeserializationContext ctxt
320314
// But then need to convert to wrappers
321315
Byte[] result = new Byte[b.length];
322316
for (int i = 0, len = b.length; i < len; ++i) {
323-
result[i] = Byte.valueOf(b[i]);
317+
result[i] = b[i];
324318
}
325319
return result;
326320
}
@@ -375,11 +369,7 @@ protected Object handleNonArray(JsonParser p, DeserializationContext ctxt)
375369
// if coercion failed, we can still add it to a list
376370
}
377371

378-
if (_elementTypeDeserializer == null) {
379-
value = _elementDeserializer.deserialize(p, ctxt);
380-
} else {
381-
value = _elementDeserializer.deserializeWithType(p, ctxt, _elementTypeDeserializer);
382-
}
372+
value = _deserializeNoNullChecks(p, ctxt);
383373
}
384374
// Ok: bit tricky, since we may want T[], not just Object[]
385375
Object[] result;
@@ -392,5 +382,21 @@ protected Object handleNonArray(JsonParser p, DeserializationContext ctxt)
392382
result[0] = value;
393383
return result;
394384
}
385+
386+
/**
387+
* Deserialize the content of the map.
388+
* If _elementTypeDeserializer is null, use _elementDeserializer.deserialize; if non-null,
389+
* use _elementDeserializer.deserializeWithType to deserialize value.
390+
* This method only performs deserialization and does not consider _skipNullValues, _nullProvider, etc.
391+
* @since 2.19.2
392+
*/
393+
protected Object _deserializeNoNullChecks(JsonParser p, DeserializationContext ctxt)
394+
throws IOException
395+
{
396+
if (_elementTypeDeserializer == null) {
397+
return _elementDeserializer.deserialize(p, ctxt);
398+
}
399+
return _elementDeserializer.deserializeWithType(p, ctxt, _elementTypeDeserializer);
400+
}
395401
}
396402

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ public final class StringArrayDeserializer
4040
/**
4141
* Value serializer to use, if not the standard one (which is inlined)
4242
*/
43-
protected JsonDeserializer<String> _elementDeserializer;
43+
private final JsonDeserializer<String> _elementDeserializer;
4444

4545
/**
4646
* Handler we need for dealing with null values as elements
4747
*
4848
* @since 2.9
4949
*/
50-
protected final NullValueProvider _nullProvider;
50+
private final NullValueProvider _nullProvider;
5151

5252
/**
5353
* Specific override for this instance (from proper, or global per-type overrides)
@@ -56,22 +56,22 @@ public final class StringArrayDeserializer
5656
*
5757
* @since 2.7
5858
*/
59-
protected final Boolean _unwrapSingle;
59+
private final Boolean _unwrapSingle;
6060

6161
/**
6262
* Marker flag set if the <code>_nullProvider</code> indicates that all null
6363
* content values should be skipped (instead of being possibly converted).
6464
*
6565
* @since 2.9
6666
*/
67-
protected final boolean _skipNullValues;
67+
private final boolean _skipNullValues;
6868

6969
public StringArrayDeserializer() {
7070
this(null, null, null);
7171
}
7272

7373
@SuppressWarnings("unchecked")
74-
protected StringArrayDeserializer(JsonDeserializer<?> deser,
74+
private StringArrayDeserializer(JsonDeserializer<?> deser,
7575
NullValueProvider nuller, Boolean unwrapSingle) {
7676
super(String[].class);
7777
_elementDeserializer = (JsonDeserializer<String>) deser;
@@ -184,7 +184,7 @@ public String[] deserialize(JsonParser p, DeserializationContext ctxt) throws IO
184184
/**
185185
* Offlined version used when we do not use the default deserialization method.
186186
*/
187-
protected final String[] _deserializeCustom(JsonParser p, DeserializationContext ctxt,
187+
private String[] _deserializeCustom(JsonParser p, DeserializationContext ctxt,
188188
String[] old) throws IOException
189189
{
190190
final ObjectBuffer buffer = ctxt.leaseObjectBuffer();

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,20 @@ public final class StringCollectionDeserializer
3737
* Value deserializer to use, if NOT the standard one
3838
* (if it is, will be null).
3939
*/
40-
protected final JsonDeserializer<String> _valueDeserializer;
40+
private final JsonDeserializer<String> _valueDeserializer;
4141

4242
// // Instance construction settings:
4343

4444
/**
4545
* Instantiator used in case custom handling is needed for creation.
4646
*/
47-
protected final ValueInstantiator _valueInstantiator;
47+
private final ValueInstantiator _valueInstantiator;
4848

4949
/**
5050
* Deserializer that is used iff delegate-based creator is
5151
* to be used for deserializing from JSON Object.
5252
*/
53-
protected final JsonDeserializer<Object> _delegateDeserializer;
53+
private final JsonDeserializer<Object> _delegateDeserializer;
5454

5555
// NOTE: no PropertyBasedCreator, as JSON Arrays have no properties
5656

@@ -67,7 +67,7 @@ public StringCollectionDeserializer(JavaType collectionType,
6767
}
6868

6969
@SuppressWarnings("unchecked")
70-
protected StringCollectionDeserializer(JavaType collectionType,
70+
private StringCollectionDeserializer(JavaType collectionType,
7171
ValueInstantiator valueInstantiator, JsonDeserializer<?> delegateDeser,
7272
JsonDeserializer<?> valueDeser,
7373
NullValueProvider nuller, Boolean unwrapSingle)
@@ -78,7 +78,7 @@ protected StringCollectionDeserializer(JavaType collectionType,
7878
_delegateDeserializer = (JsonDeserializer<Object>) delegateDeser;
7979
}
8080

81-
protected StringCollectionDeserializer withResolved(JsonDeserializer<?> delegateDeser,
81+
private StringCollectionDeserializer withResolved(JsonDeserializer<?> delegateDeser,
8282
JsonDeserializer<?> valueDeser,
8383
NullValueProvider nuller, Boolean unwrapSingle)
8484
{
@@ -107,6 +107,7 @@ public LogicalType logicalType() {
107107
/* Validation, post-processing
108108
/**********************************************************
109109
*/
110+
110111
@Override
111112
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
112113
BeanProperty property) throws JsonMappingException

src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
/**
2020
* Container class for serializers used for handling standard JDK-provided
21-
* primitve number types and their wrapper counterparts (like {@link java.lang.Integer}).
21+
* primitive number types and their wrapper counterparts (like {@link java.lang.Integer}).
2222
*/
2323
@SuppressWarnings("serial")
2424
public class NumberSerializers {

0 commit comments

Comments
 (0)