diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index 60675a43e..8590cb64f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -149,7 +149,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App TypeInformation typeToUse = getMoreConcreteTargetType(dbo, type); Class rawType = typeToUse.getType(); - if (conversions.hasCustomReadTarget(DBObject.class, rawType)) { + if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) { return conversionService.convert(dbo, rawType); } @@ -513,14 +513,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App /** * Creates a new {@link BasicDBList} from the given {@link Collection}. * - * @param type - * @param source + * @param type the {@link TypeInformation} to consider or {@literal null} if unknown. + * @param source the collection to create a {@link BasicDBList} for, must not be {@literal null}. * @return */ private BasicDBList createCollectionDBObject(TypeInformation type, Collection source) { BasicDBList dbList = new BasicDBList(); - TypeInformation componentType = type.getComponentType(); + TypeInformation componentType = type == null ? null : type.getComponentType(); for (Object element : source) { @@ -556,6 +556,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App String simpleKey = key.toString(); if (val == null || conversions.isSimpleType(val.getClass())) { writeSimpleInternal(simpleKey, val, dbo); + } else if (val instanceof Collection) { + dbo.put(simpleKey, createCollectionDBObject(propertyType.getMapValueType(), (Collection) val)); } else { DBObject newDbo = new BasicDBObject(); writeInternal(val, newDbo); @@ -576,7 +578,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App * @param value * @param dbObject */ - public void addCustomTypeKeyIfNecessary(TypeInformation type, Object value, DBObject dbObject) { + protected void addCustomTypeKeyIfNecessary(TypeInformation type, Object value, DBObject dbObject) { if (type == null) { return; @@ -801,6 +803,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App * found. */ protected Class findTypeToBeUsed(DBObject dbObject) { + + if (dbObject instanceof BasicDBList) { + return List.class; + } + Object classToBeUsed = dbObject.get(CUSTOM_TYPE_KEY); if (classToBeUsed == null) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 821559104..c8f5513d4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -528,6 +528,83 @@ public class MappingMongoConverterUnitTests { assertThat(converter.convertToMongoType(id), is((Object) id)); } + /** + * @see DATADOC-235 + */ + @Test + public void writesMapOfListsCorrectly() { + + ClassWithMapProperty input = new ClassWithMapProperty(); + input.mapOfLists = Collections.singletonMap("Foo", Arrays.asList("Bar")); + + BasicDBObject result = new BasicDBObject(); + converter.write(input, result); + + Object field = result.get("mapOfLists"); + assertThat(field, is(instanceOf(DBObject.class))); + + DBObject map = (DBObject) field; + Object foo = map.get("Foo"); + assertThat(foo, is(instanceOf(BasicDBList.class))); + + BasicDBList value = (BasicDBList) foo; + assertThat(value.size(), is(1)); + assertThat((String) value.get(0), is("Bar")); + } + + /** + * @see DATADOC-235 + */ + @Test + public void readsMapListValuesCorrectly() { + + BasicDBList list = new BasicDBList(); + list.add("Bar"); + DBObject source = new BasicDBObject("mapOfLists", new BasicDBObject("Foo", list)); + + ClassWithMapProperty result = converter.read(ClassWithMapProperty.class, source); + assertThat(result.mapOfLists, is(not(nullValue()))); + } + + /** + * @see DATADOC-235 + */ + @Test + public void writesMapsOfObjectsCorrectly() { + + ClassWithMapProperty input = new ClassWithMapProperty(); + input.mapOfObjects = new HashMap(); + input.mapOfObjects.put("Foo", Arrays.asList("Bar")); + + BasicDBObject result = new BasicDBObject(); + converter.write(input, result); + + Object field = result.get("mapOfObjects"); + assertThat(field, is(instanceOf(DBObject.class))); + + DBObject map = (DBObject) field; + Object foo = map.get("Foo"); + assertThat(foo, is(instanceOf(BasicDBList.class))); + + BasicDBList value = (BasicDBList) foo; + assertThat(value.size(), is(1)); + assertThat((String) value.get(0), is("Bar")); + } + + /** + * @see DATADOC-235 + */ + @Test + public void readsMapOfObjectsListValuesCorrectly() { + + BasicDBList list = new BasicDBList(); + list.add("Bar"); + DBObject source = new BasicDBObject("mapOfObjects", new BasicDBObject("Foo", list)); + + ClassWithMapProperty result = converter.read(ClassWithMapProperty.class, source); + assertThat(result.mapOfObjects, is(not(nullValue()))); + } + class GenericType { T content; } @@ -566,6 +643,8 @@ public class MappingMongoConverterUnitTests { class ClassWithMapProperty { Map map; + Map> mapOfLists; + Map mapOfObjects; } class ClassWithNestedMaps {