Skip to content

Commit 61d3a0b

Browse files
Fix NPE when reading/mapping null value inside collection.
Closes: #3686
1 parent 82d67c1 commit 61d3a0b

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ protected Object readCollectionOrArray(ConversionContext context, Collection<?>
12691269
}
12701270

12711271
for (Object element : source) {
1272-
items.add(context.convert(element, componentType));
1272+
items.add(element != null ? context.convert(element, componentType) : element);
12731273
}
12741274

12751275
return getPotentiallyConvertedSimpleRead(items, targetType.getType());
@@ -2013,6 +2013,7 @@ protected static class ConversionContext {
20132013
@SuppressWarnings("unchecked")
20142014
public <S extends Object> S convert(Object source, TypeInformation<? extends S> typeHint) {
20152015

2016+
Assert.notNull(source, "Source must not be null");
20162017
Assert.notNull(typeHint, "TypeInformation must not be null");
20172018

20182019
if (conversions.hasCustomReadTarget(source.getClass(), typeHint.getType())) {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ public Object readReference(MongoPersistentProperty property, Object value, Look
110110
return null;
111111
}
112112

113-
return entityReader.read(result.iterator().next(), property.getTypeInformation());
113+
Object resultValue = result.iterator().next();
114+
return resultValue != null ? entityReader.read(resultValue, property.getTypeInformation()) : null;
114115
}
115116

116117
private ReferenceCollection computeReferenceContext(MongoPersistentProperty property, Object value,

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

+39
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,41 @@ void shouldWriteNullPropertyCorrectly() {
25322532
assertThat(document).containsEntry("writeAlwaysPerson", null).doesNotContainKey("writeNonNullPerson");
25332533
}
25342534

2535+
@Test // GH-3686
2536+
void readsCollectionContainingNullValue() {
2537+
2538+
org.bson.Document source = new org.bson.Document("items", Arrays.asList(new org.bson.Document("itemKey", "i1"), null, new org.bson.Document("itemKey", "i3")));
2539+
2540+
Order target = converter.read(Order.class, source);
2541+
2542+
assertThat(target.items)
2543+
.map(it -> it != null ? it.itemKey : null)
2544+
.containsExactly("i1", null, "i3");
2545+
}
2546+
2547+
@Test // GH-3686
2548+
void readsArrayContainingNullValue() {
2549+
2550+
org.bson.Document source = new org.bson.Document("arrayOfStrings", Arrays.asList("i1", null, "i3"));
2551+
2552+
WithArrays target = converter.read(WithArrays.class, source);
2553+
2554+
assertThat(target.arrayOfStrings).containsExactly("i1", null, "i3");
2555+
}
2556+
2557+
@Test // GH-3686
2558+
void readsMapContainingNullValue() {
2559+
2560+
org.bson.Document source = new org.bson.Document("mapOfObjects", new org.bson.Document("item1", "i1").append("item2", null).append("item3", "i3"));
2561+
2562+
ClassWithMapProperty target = converter.read(ClassWithMapProperty.class, source);
2563+
2564+
assertThat(target.mapOfObjects)
2565+
.containsEntry("item1", "i1")
2566+
.containsEntry("item2", null)
2567+
.containsEntry("item3", "i3");
2568+
}
2569+
25352570
static class GenericType<T> {
25362571
T content;
25372572
}
@@ -2893,6 +2928,10 @@ static class WithArrayInConstructor {
28932928

28942929
}
28952930

2931+
static class WithArrays {
2932+
String[] arrayOfStrings;
2933+
}
2934+
28962935
// DATAMONGO-1898
28972936

28982937
// DATACMNS-1278

0 commit comments

Comments
 (0)