diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java index bdd1e577283a..655a3084de3a 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -521,7 +521,7 @@ public Jackson2ObjectMapperBuilder featuresToDisable(Object... featuresToDisable } /** - * Specify one or more modules to be registered with the {@link ObjectMapper}. + * Specify the modules to be registered with the {@link ObjectMapper}. *

Multiple invocations are not additive, the last one defines the modules to * register. *

Note: If this is set, no finding of modules is going to happen - not by @@ -538,15 +538,9 @@ public Jackson2ObjectMapperBuilder modules(Module... modules) { } /** - * Set a complete list of modules to be registered with the {@link ObjectMapper}. - *

Multiple invocations are not additive, the last one defines the modules to - * register. - *

Note: If this is set, no finding of modules is going to happen - not by - * Jackson, and not by Spring either (see {@link #findModulesViaServiceLoader}). - * As a consequence, specifying an empty list here will suppress any kind of - * module detection. - *

Specify either this or {@link #modulesToInstall}, not both. + * Variant of {@link #modules(Module...)} with a {@link List}. * @see #modules(Module...) + * @see #modules(Consumer) * @see com.fasterxml.jackson.databind.Module */ public Jackson2ObjectMapperBuilder modules(List modules) { @@ -556,6 +550,22 @@ public Jackson2ObjectMapperBuilder modules(List modules) { return this; } + /** + * Variant of {@link #modules(Module...)} with a {@link Consumer} for full + * control over the underlying list of modules. + * @since 6.0 + * @see #modules(Module...) + * @see #modules(List) + * @see com.fasterxml.jackson.databind.Module + */ + public Jackson2ObjectMapperBuilder modules(Consumer> consumer) { + this.modules = (this.modules != null ? this.modules : new ArrayList<>()); + this.findModulesViaServiceLoader = false; + this.findWellKnownModules = false; + consumer.accept(this.modules); + return this; + } + /** * Specify one or more modules to be registered with the {@link ObjectMapper}. *

Multiple invocations are not additive, the last one defines the modules @@ -566,6 +576,7 @@ public Jackson2ObjectMapperBuilder modules(List modules) { * allowing to eventually override their configuration. *

Specify either this or {@link #modules(Module...)}, not both. * @since 4.1.5 + * @see #modulesToInstall(Consumer) * @see #modulesToInstall(Class...) * @see com.fasterxml.jackson.databind.Module */ @@ -575,6 +586,21 @@ public Jackson2ObjectMapperBuilder modulesToInstall(Module... modules) { return this; } + /** + * Variant of {@link #modulesToInstall(Module...)} with a {@link Consumer} + * for full control over the underlying list of modules. + * @since 6.0 + * @see #modulesToInstall(Module...) + * @see #modulesToInstall(Class...) + * @see com.fasterxml.jackson.databind.Module + */ + public Jackson2ObjectMapperBuilder modulesToInstall(Consumer> consumer) { + this.modules = (this.modules != null ? this.modules : new ArrayList<>()); + this.findWellKnownModules = true; + consumer.accept(this.modules); + return this; + } + /** * Specify one or more modules by class to be registered with * the {@link ObjectMapper}. @@ -586,6 +612,7 @@ public Jackson2ObjectMapperBuilder modulesToInstall(Module... modules) { * allowing to eventually override their configuration. *

Specify either this or {@link #modules(Module...)}, not both. * @see #modulesToInstall(Module...) + * @see #modulesToInstall(Consumer) * @see com.fasterxml.jackson.databind.Module */ @SafeVarargs diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java index 32a93851ba46..f1a5748d2725 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -241,6 +241,16 @@ void modules() { assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null)).isSameAs(serializer1); } + @Test + void modulesWithConsumer() { + NumberSerializer serializer1 = new NumberSerializer(Integer.class); + SimpleModule module = new SimpleModule(); + module.addSerializer(Integer.class, serializer1); + ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(list -> list.add(module) ).build(); + Serializers serializers = getSerializerFactoryConfig(objectMapper).serializers().iterator().next(); + assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null)).isSameAs(serializer1); + } + @Test void modulesToInstallByClass() { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json() @@ -259,6 +269,15 @@ void modulesToInstallByInstance() { assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null).getClass()).isSameAs(CustomIntegerSerializer.class); } + @Test + void modulesToInstallWithConsumer() { + ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json() + .modulesToInstall(list -> list.add(new CustomIntegerModule())) + .build(); + Serializers serializers = getSerializerFactoryConfig(objectMapper).serializers().iterator().next(); + assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null).getClass()).isSameAs(CustomIntegerSerializer.class); + } + @Test void wellKnownModules() throws JsonProcessingException, UnsupportedEncodingException { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();