2727import org .springframework .data .mapping .PersistentProperty ;
2828import org .springframework .data .mapping .context .MappingContext ;
2929import org .springframework .data .mongodb .core .convert .MongoConverter ;
30- import org .springframework .data .mongodb .core .mapping .BasicMongoPersistentEntity ;
3130import org .springframework .data .mongodb .core .mapping .Encrypted ;
3231import org .springframework .data .mongodb .core .mapping .Field ;
3332import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
3433import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
34+ import org .springframework .data .mongodb .core .schema .IdentifiableJsonSchemaProperty .ArrayJsonSchemaProperty ;
3535import org .springframework .data .mongodb .core .schema .IdentifiableJsonSchemaProperty .EncryptedJsonSchemaProperty ;
3636import org .springframework .data .mongodb .core .schema .IdentifiableJsonSchemaProperty .ObjectJsonSchemaProperty ;
3737import org .springframework .data .mongodb .core .schema .JsonSchemaObject ;
@@ -160,15 +160,15 @@ private JsonSchemaProperty computeSchemaForProperty(List<MongoPersistentProperty
160160 Class <?> rawTargetType = computeTargetType (property ); // target type before conversion
161161 Class <?> targetType = converter .getTypeMapper ().getWriteTargetTypeFor (rawTargetType ); // conversion target type
162162
163- if (property .isEntity () && ObjectUtils .nullSafeEquals (rawTargetType , targetType )) {
163+ if (! isCollection ( property ) && property .isEntity () && ObjectUtils .nullSafeEquals (rawTargetType , targetType )) {
164164 return createObjectSchemaPropertyForEntity (path , property , required );
165165 }
166166
167167 String fieldName = computePropertyFieldName (property );
168168
169169 JsonSchemaProperty schemaProperty ;
170- if (property . isCollectionLike ( )) {
171- schemaProperty = createSchemaProperty (fieldName , targetType , required );
170+ if (isCollection ( property )) {
171+ schemaProperty = createSchemaPropertyForCollection (fieldName , property , required );
172172 } else if (property .isMap ()) {
173173 schemaProperty = createSchemaProperty (fieldName , Type .objectType (), required );
174174 } else if (ClassUtils .isAssignable (Enum .class , targetType )) {
@@ -180,6 +180,48 @@ private JsonSchemaProperty computeSchemaForProperty(List<MongoPersistentProperty
180180 return applyEncryptionDataIfNecessary (property , schemaProperty );
181181 }
182182
183+ private JsonSchemaProperty createSchemaPropertyForCollection (String fieldName , MongoPersistentProperty property ,
184+ boolean required ) {
185+
186+ ArrayJsonSchemaProperty schemaProperty = JsonSchemaProperty .array (fieldName );
187+
188+ if (property .getActualType () != Object .class ) {
189+
190+ MongoPersistentEntity <?> persistentEntity = mappingContext
191+ .getPersistentEntity (property .getTypeInformation ().getComponentType ());
192+
193+ if (persistentEntity == null ) {
194+
195+ if (ClassUtils .isAssignable (Enum .class , property .getActualType ())) {
196+
197+ List <Object > possibleValues = new ArrayList <>();
198+
199+ for (Object enumValue : EnumSet .allOf ((Class ) property .getActualType ())) {
200+ possibleValues .add (converter .convertToMongoType (enumValue ));
201+ }
202+
203+ Class targetType = possibleValues .isEmpty () ? property .getActualType ()
204+ : possibleValues .iterator ().next ().getClass ();
205+ schemaProperty = schemaProperty
206+ .items (Collections .singleton (JsonSchemaObject .of (targetType ).possibleValues (possibleValues )));
207+ } else {
208+ schemaProperty = schemaProperty .items (Collections .singleton (JsonSchemaObject .of (property .getActualType ())));
209+ }
210+ } else {
211+
212+ List <JsonSchemaProperty > nestedProperties = computePropertiesForEntity (Collections .emptyList (),
213+ persistentEntity );
214+
215+ if (!nestedProperties .isEmpty ()) {
216+ schemaProperty = schemaProperty .items (Collections
217+ .singleton (JsonSchemaObject .object ().properties (nestedProperties .toArray (new JsonSchemaProperty [0 ]))));
218+ }
219+ }
220+ }
221+
222+ return createPotentiallyRequiredSchemaProperty (schemaProperty , required );
223+ }
224+
183225 @ Nullable
184226 private JsonSchemaProperty applyEncryptionDataIfNecessary (MongoPersistentProperty property ,
185227 JsonSchemaProperty schemaProperty ) {
@@ -197,7 +239,6 @@ private JsonSchemaProperty applyEncryptionDataIfNecessary(MongoPersistentPropert
197239 enc = enc .keys (property .getEncryptionKeyIds ());
198240 }
199241 return enc ;
200-
201242 }
202243
203244 private JsonSchemaProperty createObjectSchemaPropertyForEntity (List <MongoPersistentProperty > path ,
@@ -268,6 +309,10 @@ private Class<?> computeTargetType(PersistentProperty<?> property) {
268309 return mongoProperty .getFieldType () != mongoProperty .getActualType () ? Object .class : mongoProperty .getFieldType ();
269310 }
270311
312+ private static boolean isCollection (MongoPersistentProperty property ) {
313+ return property .isCollectionLike () && !property .getType ().equals (byte [].class );
314+ }
315+
271316 static JsonSchemaProperty createPotentiallyRequiredSchemaProperty (JsonSchemaProperty property , boolean required ) {
272317
273318 if (!required ) {
0 commit comments