Use JsonMapper instead of ObjectMapper where feasible

See gh-47503

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
This commit is contained in:
Yanming Zhou
2025-10-20 13:16:52 +02:00
committed by Stéphane Nicoll
parent f1178e6481
commit 609b0b444e
32 changed files with 121 additions and 133 deletions
@@ -41,7 +41,7 @@ import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.TaskProvider;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
@@ -197,8 +197,8 @@ public class AntoraConventions {
private String getUiBundleUrl(Project project) {
File packageJson = project.getRootProject().file("antora/package.json");
ObjectMapper objectMapper = new ObjectMapper();
Map<?, ?> json = objectMapper.readerFor(Map.class).readValue(packageJson);
JsonMapper jsonMapper = new JsonMapper();
Map<?, ?> json = jsonMapper.readerFor(Map.class).readValue(packageJson);
Map<?, ?> config = (json != null) ? (Map<?, ?>) json.get("config") : null;
String url = (config != null) ? (String) config.get("ui-bundle-url") : null;
Assert.state(StringUtils.hasText(url.toString()), "package.json has not ui-bundle-url config");
@@ -25,7 +25,6 @@ import java.net.URI;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
@@ -37,17 +36,17 @@ import tools.jackson.databind.json.JsonMapper;
*/
public record ResolvedBom(Id id, List<ResolvedLibrary> libraries) {
private static final ObjectMapper objectMapper;
private static final JsonMapper jsonMapper;
static {
objectMapper = JsonMapper.builder()
jsonMapper = JsonMapper.builder()
.changeDefaultPropertyInclusion((value) -> value.withContentInclusion(Include.NON_EMPTY))
.build();
}
public static ResolvedBom readFrom(File file) {
try (FileReader reader = new FileReader(file)) {
return objectMapper.readValue(reader, ResolvedBom.class);
return jsonMapper.readValue(reader, ResolvedBom.class);
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
@@ -55,7 +54,7 @@ public record ResolvedBom(Id id, List<ResolvedLibrary> libraries) {
}
public void writeTo(Writer writer) {
objectMapper.writeValue(writer, this);
jsonMapper.writeValue(writer, this);
}
public record ResolvedLibrary(String name, String version, String versionProperty, List<Id> managedDependencies,
@@ -37,7 +37,7 @@ import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SourceTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.VerificationException;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
* {@link SourceTask} that checks additional Spring configuration metadata files.
@@ -75,11 +75,11 @@ public abstract class CheckAdditionalSpringConfigurationMetadata extends SourceT
@SuppressWarnings("unchecked")
private Report createReport() {
ObjectMapper objectMapper = new ObjectMapper();
JsonMapper jsonMapper = new JsonMapper();
Report report = new Report();
for (File file : getSource().getFiles()) {
Analysis analysis = report.analysis(this.projectDir.toPath().relativize(file.toPath()));
Map<String, Object> json = objectMapper.readValue(file, Map.class);
Map<String, Object> json = jsonMapper.readValue(file, Map.class);
check("groups", json, analysis);
check("properties", json, analysis);
check("hints", json, analysis);
@@ -37,7 +37,7 @@ import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SourceTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.VerificationException;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
* {@link SourceTask} that checks {@code spring-configuration-metadata.json} files.
@@ -75,10 +75,10 @@ public abstract class CheckSpringConfigurationMetadata extends DefaultTask {
@SuppressWarnings("unchecked")
private Report createReport() {
ObjectMapper objectMapper = new ObjectMapper();
JsonMapper jsonMapper = new JsonMapper();
File file = getMetadataLocation().get().getAsFile();
Report report = new Report(this.projectRoot.relativize(file.toPath()));
Map<String, Object> json = objectMapper.readValue(file, Map.class);
Map<String, Object> json = jsonMapper.readValue(file, Map.class);
List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties");
for (Map<String, Object> property : properties) {
String name = (String) property.get("name");
@@ -24,7 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
* Configuration properties read from one or more
@@ -55,10 +55,10 @@ final class ConfigurationProperties {
@SuppressWarnings("unchecked")
static ConfigurationProperties fromFiles(Iterable<File> files) {
ObjectMapper objectMapper = new ObjectMapper();
JsonMapper jsonMapper = new JsonMapper();
List<ConfigurationProperty> properties = new ArrayList<>();
for (File file : files) {
Map<String, Object> json = objectMapper.readValue(file, Map.class);
Map<String, Object> json = jsonMapper.readValue(file, Map.class);
for (Map<String, Object> property : (List<Map<String, Object>>) json.get("properties")) {
properties.add(ConfigurationProperty.fromJsonProperties(property));
}
@@ -31,7 +31,7 @@ import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.node.ArrayNode;
import tools.jackson.databind.node.ObjectNode;
@@ -67,7 +67,7 @@ public class ImageArchive implements TarArchive {
private static final IOConsumer<Update> NO_UPDATES = (update) -> {
};
private final ObjectMapper objectMapper;
private final JsonMapper jsonMapper;
private final ImageConfig imageConfig;
@@ -85,10 +85,10 @@ public class ImageArchive implements TarArchive {
private final List<Layer> newLayers;
ImageArchive(ObjectMapper objectMapper, ImageConfig imageConfig, Instant createDate, @Nullable ImageReference tag,
ImageArchive(JsonMapper jsonMapper, ImageConfig imageConfig, Instant createDate, @Nullable ImageReference tag,
String os, @Nullable String architecture, @Nullable String variant, List<LayerId> existingLayers,
List<Layer> newLayers) {
this.objectMapper = objectMapper;
this.jsonMapper = jsonMapper;
this.imageConfig = imageConfig;
this.createDate = createDate;
this.tag = tag;
@@ -158,7 +158,7 @@ public class ImageArchive implements TarArchive {
private String writeConfig(Layout writer, List<LayerId> writtenLayers) throws IOException {
try {
ObjectNode config = createConfig(writtenLayers);
String json = this.objectMapper.writeValueAsString(config).replace("\r\n", "\n");
String json = this.jsonMapper.writeValueAsString(config).replace("\r\n", "\n");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
InspectedContent content = InspectedContent.of(Content.of(json), digest::update);
String name = LayerId.ofSha256Digest(digest.digest()).getHash() + ".json";
@@ -171,7 +171,7 @@ public class ImageArchive implements TarArchive {
}
private ObjectNode createConfig(List<LayerId> writtenLayers) {
ObjectNode config = this.objectMapper.createObjectNode();
ObjectNode config = this.jsonMapper.createObjectNode();
config.set("Config", this.imageConfig.getNodeCopy());
config.set("Created", config.stringNode(getCreatedDate()));
config.set("History", createHistory(writtenLayers));
@@ -187,7 +187,7 @@ public class ImageArchive implements TarArchive {
}
private JsonNode createHistory(List<LayerId> writtenLayers) {
ArrayNode history = this.objectMapper.createArrayNode();
ArrayNode history = this.jsonMapper.createArrayNode();
int size = this.existingLayers.size() + writtenLayers.size();
for (int i = 0; i < size; i++) {
history.addObject();
@@ -196,7 +196,7 @@ public class ImageArchive implements TarArchive {
}
private JsonNode createRootFs(List<LayerId> writtenLayers) {
ObjectNode rootFs = this.objectMapper.createObjectNode();
ObjectNode rootFs = this.jsonMapper.createObjectNode();
ArrayNode diffIds = rootFs.putArray("diff_ids");
this.existingLayers.stream().map(Object::toString).forEach(diffIds::add);
writtenLayers.stream().map(Object::toString).forEach(diffIds::add);
@@ -205,12 +205,12 @@ public class ImageArchive implements TarArchive {
private void writeManifest(Layout writer, String config, List<LayerId> writtenLayers) throws IOException {
ArrayNode manifest = createManifest(config, writtenLayers);
String manifestJson = this.objectMapper.writeValueAsString(manifest);
String manifestJson = this.jsonMapper.writeValueAsString(manifest);
writer.file("manifest.json", Owner.ROOT, Content.of(manifestJson));
}
private ArrayNode createManifest(String config, List<LayerId> writtenLayers) {
ArrayNode manifest = this.objectMapper.createArrayNode();
ArrayNode manifest = this.jsonMapper.createArrayNode();
ObjectNode entry = manifest.addObject();
entry.set("Config", entry.stringNode(config));
entry.set("Layers", getManifestLayers(writtenLayers));
@@ -221,7 +221,7 @@ public class ImageArchive implements TarArchive {
}
private ArrayNode getManifestLayers(List<LayerId> writtenLayers) {
ArrayNode layers = this.objectMapper.createArrayNode();
ArrayNode layers = this.jsonMapper.createArrayNode();
for (int i = 0; i < this.existingLayers.size(); i++) {
layers.add(EMPTY_LAYER_NAME_PREFIX + i);
}
@@ -33,7 +33,6 @@ import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.util.Assert;
@@ -162,7 +161,7 @@ public class MappedObject {
* @throws IOException on IO error
*/
protected static <T extends MappedObject> T of(String content, Function<JsonNode, T> factory) throws IOException {
return of(content, ObjectMapper::readTree, factory);
return of(content, JsonMapper::readTree, factory);
}
/**
@@ -175,7 +174,7 @@ public class MappedObject {
*/
protected static <T extends MappedObject> T of(InputStream content, Function<JsonNode, T> factory)
throws IOException {
return of(StreamUtils.nonClosing(content), ObjectMapper::readTree, factory);
return of(StreamUtils.nonClosing(content), JsonMapper::readTree, factory);
}
/**
@@ -205,12 +204,12 @@ public class MappedObject {
/**
* Read JSON content as a {@link JsonNode}.
* @param objectMapper the source object mapper
* @param jsonMapper the source json mapper
* @param content the content to read
* @return a {@link JsonNode}
* @throws IOException on IO error
*/
JsonNode read(ObjectMapper objectMapper, C content) throws IOException;
JsonNode read(JsonMapper jsonMapper, C content) throws IOException;
}
@@ -22,7 +22,6 @@ import java.util.Locale;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.MapperFeature;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
@@ -34,7 +33,7 @@ import tools.jackson.databind.json.JsonMapper;
*/
final class DockerJson {
private static final ObjectMapper objectMapper = JsonMapper.builder()
private static final JsonMapper jsonMapper = JsonMapper.builder()
.defaultLocale(Locale.ENGLISH)
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
@@ -53,7 +52,7 @@ final class DockerJson {
*/
static <T> List<T> deserializeToList(String json, Class<T> itemType) {
if (json.startsWith("[")) {
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, itemType);
JavaType javaType = jsonMapper.getTypeFactory().constructCollectionType(List.class, itemType);
return deserialize(json, javaType);
}
return json.trim().lines().map((line) -> deserialize(line, itemType)).toList();
@@ -67,11 +66,11 @@ final class DockerJson {
* @return the deserialized result
*/
static <T> T deserialize(String json, Class<T> type) {
return deserialize(json, objectMapper.getTypeFactory().constructType(type));
return deserialize(json, jsonMapper.getTypeFactory().constructType(type));
}
private static <T> T deserialize(String json, JavaType type) {
return objectMapper.readValue(json.trim(), type);
return jsonMapper.readValue(json.trim(), type);
}
}
@@ -37,7 +37,6 @@ import org.jspecify.annotations.Nullable;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.ObjectReader;
import tools.jackson.databind.ObjectWriter;
import tools.jackson.databind.json.JsonMapper;
@@ -222,13 +221,13 @@ public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {
private static final class JacksonJsonProvider extends AbstractJsonProvider {
private final ObjectMapper objectMapper;
private final JsonMapper jsonMapper;
private final ObjectReader objectReader;
private JacksonJsonProvider(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
this.objectReader = objectMapper.reader().forType(Object.class);
private JacksonJsonProvider(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
this.objectReader = jsonMapper.reader().forType(Object.class);
}
@Override
@@ -264,8 +263,8 @@ public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {
@Override
public String toJson(Object obj) {
StringWriter writer = new StringWriter();
try (JsonGenerator generator = this.objectMapper.createGenerator(writer)) {
this.objectMapper.writeValue(generator, obj);
try (JsonGenerator generator = this.jsonMapper.createGenerator(writer)) {
this.jsonMapper.writeValue(generator, obj);
}
catch (JacksonException ex) {
throw new InvalidJsonException(ex);
@@ -287,10 +286,10 @@ public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {
private static final class JacksonMappingProvider implements MappingProvider {
private final ObjectMapper objectMapper;
private final JsonMapper jsonMapper;
private JacksonMappingProvider(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
private JacksonMappingProvider(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
@Override
@@ -299,7 +298,7 @@ public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {
return null;
}
try {
return this.objectMapper.convertValue(source, targetType);
return this.jsonMapper.convertValue(source, targetType);
}
catch (Exception ex) {
throw new MappingException(ex);
@@ -313,9 +312,9 @@ public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {
if (source == null) {
return null;
}
JavaType type = this.objectMapper.getTypeFactory().constructType(targetType.getType());
JavaType type = this.jsonMapper.getTypeFactory().constructType(targetType.getType());
try {
return (T) this.objectMapper.convertValue(source, type);
return (T) this.jsonMapper.convertValue(source, type);
}
catch (Exception ex) {
throw new MappingException(ex);
@@ -21,10 +21,10 @@ import java.util.Map;
import org.jspecify.annotations.Nullable;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
/**
* Thin wrapper to adapt Jackson 2 {@link ObjectMapper} to {@link JsonParser}.
* Thin wrapper to adapt Jackson 3 {@link JsonMapper} to {@link JsonParser}.
*
* @author Dave Syer
* @since 1.0.0
@@ -36,37 +36,37 @@ public class JacksonJsonParser extends AbstractJsonParser {
private static final ListTypeReference LIST_TYPE = new ListTypeReference();
private @Nullable ObjectMapper objectMapper; // Late binding
private @Nullable JsonMapper jsonMapper; // Late binding
/**
* Creates an instance with the specified {@link ObjectMapper}.
* @param objectMapper the object mapper to use
* Creates an instance with the specified {@link JsonMapper}.
* @param jsonMapper the json mapper to use
*/
public JacksonJsonParser(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
public JacksonJsonParser(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
/**
* Creates an instance with a default {@link ObjectMapper} that is created lazily.
* Creates an instance with a default {@link JsonMapper} that is created lazily.
*/
public JacksonJsonParser() {
}
@Override
public Map<String, Object> parseMap(@Nullable String json) {
return tryParse(() -> getObjectMapper().readValue(json, MAP_TYPE), Exception.class);
return tryParse(() -> getJsonMapper().readValue(json, MAP_TYPE), Exception.class);
}
@Override
public List<Object> parseList(@Nullable String json) {
return tryParse(() -> getObjectMapper().readValue(json, LIST_TYPE), Exception.class);
return tryParse(() -> getJsonMapper().readValue(json, LIST_TYPE), Exception.class);
}
private ObjectMapper getObjectMapper() {
if (this.objectMapper == null) {
this.objectMapper = new ObjectMapper();
private JsonMapper getJsonMapper() {
if (this.jsonMapper == null) {
this.jsonMapper = new JsonMapper();
}
return this.objectMapper;
return this.jsonMapper;
}
private static final class MapTypeReference extends TypeReference<Map<String, Object>> {
@@ -19,7 +19,7 @@ package org.springframework.boot.json;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -42,9 +42,9 @@ class JacksonJsonParserTests extends AbstractJsonParserTests {
@Test
@SuppressWarnings("unchecked")
void instanceWithSpecificObjectMapper() {
ObjectMapper objectMapper = spy(new ObjectMapper());
new JacksonJsonParser(objectMapper).parseMap("{}");
then(objectMapper).should().readValue(eq("{}"), any(TypeReference.class));
JsonMapper jsonMapper = spy(new JsonMapper());
new JacksonJsonParser(jsonMapper).parseMap("{}");
then(jsonMapper).should().readValue(eq("{}"), any(TypeReference.class));
}
@Override
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.logging.structured.MockStructuredLoggingJsonMembersCustomizerBuilder;
import org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer;
@@ -45,7 +45,7 @@ abstract class AbstractStructuredLoggingTests {
static final Instant EVENT_TIME = Instant.ofEpochMilli(1719910193000L);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final JsonMapper JSON_MAPPER = new JsonMapper();
@Mock
@SuppressWarnings("NullAway.Init")
@@ -79,7 +79,7 @@ abstract class AbstractStructuredLoggingTests {
}
protected Map<String, Object> deserialize(String json) {
return OBJECT_MAPPER.readValue(json, new TypeReference<>() {
return JSON_MAPPER.readValue(json, new TypeReference<>() {
});
}
@@ -36,7 +36,7 @@ import org.slf4j.Marker;
import org.slf4j.event.KeyValuePair;
import org.slf4j.helpers.BasicMarkerFactory;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.logging.structured.MockStructuredLoggingJsonMembersCustomizerBuilder;
import org.springframework.boot.logging.structured.StructuredLoggingJsonMembersCustomizer;
@@ -53,7 +53,7 @@ abstract class AbstractStructuredLoggingTests {
static final Instant EVENT_TIME = Instant.ofEpochSecond(1719910193L);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final JsonMapper JSON_MAPPER = new JsonMapper();
private ThrowableProxyConverter throwableProxyConverter;
@@ -122,7 +122,7 @@ abstract class AbstractStructuredLoggingTests {
}
protected Map<String, Object> deserialize(String json) {
return OBJECT_MAPPER.readValue(json, new TypeReference<>() {
return JSON_MAPPER.readValue(json, new TypeReference<>() {
});
}
@@ -19,7 +19,7 @@ package org.springframework.boot.web.error;
import java.util.List;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.support.DefaultMessageSourceResolvable;
@@ -46,7 +46,7 @@ class ErrorTests {
@Test
void errorCauseDoesNotAppearInJson() {
String json = new ObjectMapper()
String json = new JsonMapper()
.writeValueAsString(Error.wrapIfNecessary(List.of(new CustomMessageSourceResolvable("code"))));
assertThat(json).doesNotContain("some detail");
}
@@ -76,8 +76,8 @@ public abstract class AbstractEndpointDocumentationTests {
@SuppressWarnings("unchecked")
protected <T> OperationPreprocessor limit(Predicate<T> filter, String... keys) {
return new ContentModifyingOperationPreprocessor((content, mediaType) -> {
JsonMapper objectMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
JsonMapper jsonMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
Map<String, Object> payload = jsonMapper.readValue(content, Map.class);
Object target = payload;
Map<Object, Object> parent = null;
for (String key : keys) {
@@ -93,7 +93,7 @@ public abstract class AbstractEndpointDocumentationTests {
else {
parent.put(keys[keys.length - 1], select((List<Object>) target, filter));
}
return objectMapper.writeValueAsBytes(payload);
return jsonMapper.writeValueAsBytes(payload);
});
}
@@ -24,7 +24,6 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.SerializationFeature;
import tools.jackson.databind.json.JsonMapper;
@@ -116,8 +115,8 @@ class EnvironmentEndpointDocumentationTests extends MockMvcEndpointDocumentation
@SuppressWarnings("unchecked")
private byte[] filterProperties(byte[] content, MediaType mediaType) {
ObjectMapper objectMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
JsonMapper jsonMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
Map<String, Object> payload = jsonMapper.readValue(content, Map.class);
List<Map<String, Object>> propertySources = (List<Map<String, Object>>) payload.get("propertySources");
for (Map<String, Object> propertySource : propertySources) {
Map<String, String> properties = (Map<String, String>) propertySource.get("properties");
@@ -128,7 +127,7 @@ class EnvironmentEndpointDocumentationTests extends MockMvcEndpointDocumentation
.collect(Collectors.toSet());
properties.keySet().retainAll(filteredKeys);
}
return objectMapper.writeValueAsBytes(payload);
return jsonMapper.writeValueAsBytes(payload);
}
private boolean retainKey(String key) {
@@ -24,7 +24,7 @@ import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
import org.springframework.boot.micrometer.metrics.actuate.endpoint.MetricsEndpoint;
@@ -44,7 +44,7 @@ class MetricsEndpointWebIntegrationTests {
private static final MeterRegistry registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock());
private final ObjectMapper mapper = new ObjectMapper();
private final JsonMapper mapper = new JsonMapper();
@WebEndpointTest
@SuppressWarnings("unchecked")
@@ -17,7 +17,6 @@
package org.springframework.boot.actuate.autoconfigure.endpoint.jackson;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.actuate.endpoint.jackson.EndpointJsonMapper;
@@ -34,7 +33,7 @@ import org.springframework.context.annotation.Bean;
* @since 3.0.0
*/
@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnClass(JsonMapper.class)
public final class JacksonEndpointAutoConfiguration {
@Bean
@@ -18,7 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.jmx;
import javax.management.MBeanServer;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.LazyInitializationExcludeFilter;
@@ -100,11 +100,10 @@ public final class JmxEndpointAutoConfiguration {
@Bean
@ConditionalOnSingleCandidate(MBeanServer.class)
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnClass(JsonMapper.class)
JmxEndpointExporter jmxMBeanExporter(MBeanServer mBeanServer, EndpointObjectNameFactory endpointObjectNameFactory,
ObjectProvider<ObjectMapper> objectMapper, JmxEndpointsSupplier jmxEndpointsSupplier) {
JmxOperationResponseMapper responseMapper = new JacksonJmxOperationResponseMapper(
objectMapper.getIfAvailable());
ObjectProvider<JsonMapper> jsonMapper, JmxEndpointsSupplier jmxEndpointsSupplier) {
JmxOperationResponseMapper responseMapper = new JacksonJmxOperationResponseMapper(jsonMapper.getIfAvailable());
return new JmxEndpointExporter(mBeanServer, endpointObjectNameFactory, responseMapper,
jmxEndpointsSupplier.getEndpoints());
}
@@ -19,14 +19,14 @@ package org.springframework.boot.actuate.endpoint;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.lang.Contract;
/**
* Tagging interface used to indicate that an operation result is intended to be returned
* in the body of the response. Primarily intended to support JSON serialization using an
* endpoint specific {@link ObjectMapper}.
* endpoint specific {@link JsonMapper}.
*
* @author Phillip Webb
* @since 3.0.0
@@ -22,12 +22,12 @@ import java.util.Map;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.lang.Contract;
/**
* {@link JmxOperationResponseMapper} that delegates to a Jackson {@link ObjectMapper} to
* {@link JmxOperationResponseMapper} that delegates to a Jackson {@link JsonMapper} to
* return a JSON response.
*
* @author Stephane Nicoll
@@ -35,17 +35,16 @@ import org.springframework.lang.Contract;
*/
public class JacksonJmxOperationResponseMapper implements JmxOperationResponseMapper {
private final ObjectMapper objectMapper;
private final JsonMapper jsonMapper;
private final JavaType listType;
private final JavaType mapType;
public JacksonJmxOperationResponseMapper(@Nullable ObjectMapper objectMapper) {
this.objectMapper = (objectMapper != null) ? objectMapper : new ObjectMapper();
this.listType = this.objectMapper.getTypeFactory().constructParametricType(List.class, Object.class);
this.mapType = this.objectMapper.getTypeFactory()
.constructParametricType(Map.class, String.class, Object.class);
public JacksonJmxOperationResponseMapper(@Nullable JsonMapper jsonMapper) {
this.jsonMapper = (jsonMapper != null) ? jsonMapper : new JsonMapper();
this.listType = this.jsonMapper.getTypeFactory().constructParametricType(List.class, Object.class);
this.mapType = this.jsonMapper.getTypeFactory().constructParametricType(Map.class, String.class, Object.class);
}
@Override
@@ -69,9 +68,9 @@ public class JacksonJmxOperationResponseMapper implements JmxOperationResponseMa
return response.toString();
}
if (response.getClass().isArray() || response instanceof Collection) {
return this.objectMapper.convertValue(response, this.listType);
return this.jsonMapper.convertValue(response, this.listType);
}
return this.objectMapper.convertValue(response, this.mapType);
return this.jsonMapper.convertValue(response, this.mapType);
}
}
@@ -20,7 +20,7 @@ import java.util.Collections;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -75,7 +75,7 @@ class AuditEventTests {
void jsonFormat() throws Exception {
AuditEvent event = new AuditEvent("johannes", "UNKNOWN",
Collections.singletonMap("type", (Object) "BadCredentials"));
String json = new ObjectMapper().writeValueAsString(event);
String json = new JsonMapper().writeValueAsString(event);
JSONObject jsonObject = new JSONObject(json);
assertThat(jsonObject.getString("type")).isEqualTo("UNKNOWN");
assertThat(jsonObject.getJSONObject("data").getString("type")).isEqualTo("BadCredentials");
@@ -26,7 +26,7 @@ import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.test.json.BasicJsonTester;
@@ -56,11 +56,11 @@ class JacksonJmxOperationResponseMapperTests {
@Test
void createWhenObjectMapperIsSpecifiedShouldUseObjectMapper() {
ObjectMapper objectMapper = spy(ObjectMapper.class);
JacksonJmxOperationResponseMapper mapper = new JacksonJmxOperationResponseMapper(objectMapper);
JsonMapper jsonMapper = spy(JsonMapper.class);
JacksonJmxOperationResponseMapper mapper = new JacksonJmxOperationResponseMapper(jsonMapper);
Set<String> response = Collections.singleton("test");
mapper.mapResponse(response);
then(objectMapper).should().convertValue(eq(response), any(JavaType.class));
then(jsonMapper).should().convertValue(eq(response), any(JavaType.class));
}
@Test
@@ -22,7 +22,6 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.MapperFeature;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.actuate.endpoint.ApiVersion;
@@ -76,7 +75,7 @@ class CompositeHealthDescriptorTests {
components.put("db1", new IndicatedHealthDescriptor(Health.up().build()));
components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build()));
CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V3, Status.UP, components);
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo("""
{"components":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}""");
@@ -88,7 +87,7 @@ class CompositeHealthDescriptorTests {
components.put("db1", new IndicatedHealthDescriptor(Health.up().build()));
components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build()));
CompositeHealthDescriptor descriptor = new CompositeHealthDescriptor(ApiVersion.V2, Status.UP, components);
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo("""
{"details":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}""");
@@ -18,7 +18,6 @@ package org.springframework.boot.health.actuate.endpoint;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.MapperFeature;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.health.contributor.Health;
@@ -36,7 +35,7 @@ class IndicatedHealthDescriptorTests {
void serializeWithJacksonReturnsValidJson() throws Exception {
IndicatedHealthDescriptor descriptor = new IndicatedHealthDescriptor(
Health.outOfService().withDetail("spring", "boot").build());
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo("""
{"details":{"spring":"boot"},"status":"OUT_OF_SERVICE"}""");
@@ -45,7 +44,7 @@ class IndicatedHealthDescriptorTests {
@Test
void serializeWithJacksonWhenEmptyDetailsReturnsValidJson() throws Exception {
IndicatedHealthDescriptor descriptor = new IndicatedHealthDescriptor(Health.outOfService().build());
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo("""
{"status":"OUT_OF_SERVICE"}""");
@@ -24,7 +24,6 @@ import java.util.Set;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.MapperFeature;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.actuate.endpoint.ApiVersion;
@@ -47,7 +46,7 @@ class SystemHealthDescriptorTests {
components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build()));
Set<String> groups = new LinkedHashSet<>(Arrays.asList("liveness", "readiness"));
SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V3, Status.UP, components, groups);
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo(
"""
@@ -60,7 +59,7 @@ class SystemHealthDescriptorTests {
components.put("db1", new IndicatedHealthDescriptor(Health.up().build()));
components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build()));
SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V3, Status.UP, components, null);
ObjectMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
String json = mapper.writeValueAsString(descriptor);
assertThat(json).isEqualTo("""
{"components":{"db1":{"status":"UP"},"db2":{"details":{"a":"b"},"status":"DOWN"}},"status":"UP"}""");
@@ -72,7 +71,7 @@ class SystemHealthDescriptorTests {
components.put("db1", new IndicatedHealthDescriptor(Health.up().build()));
components.put("db2", new IndicatedHealthDescriptor(Health.down().withDetail("a", "b").build()));
SystemHealthDescriptor descriptor = new SystemHealthDescriptor(ApiVersion.V2, Status.UP, components, null);
ObjectMapper mapper = JsonMapper.builder()
JsonMapper mapper = JsonMapper.builder()
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)
.build();
@@ -21,7 +21,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -182,7 +182,7 @@ class HealthTests {
@Test
void serializeWithJacksonReturnsValidJson() throws Exception {
Health health = Health.down().withDetail("a", "b").build();
ObjectMapper mapper = new ObjectMapper();
JsonMapper mapper = new JsonMapper();
String json = mapper.writeValueAsString(health);
assertThat(json).isEqualTo("{\"details\":{\"a\":\"b\"},\"status\":\"DOWN\"}");
}
@@ -17,7 +17,7 @@
package org.springframework.boot.health.contributor;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -72,7 +72,7 @@ class StatusTests {
@Test
void serializeWithJacksonReturnsValidJson() throws Exception {
Status status = new Status("spring", "boot");
ObjectMapper mapper = new ObjectMapper();
JsonMapper mapper = new JsonMapper();
String json = mapper.writeValueAsString(status);
assertThat(json).isEqualTo("{\"description\":\"boot\",\"status\":\"spring\"}");
}
@@ -27,7 +27,6 @@ import org.junit.jupiter.api.Test;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.module.SimpleModule;
import tools.jackson.databind.node.NullNode;
@@ -55,7 +54,7 @@ class ObjectValueDeserializerTests {
Deserializer deserializer = new NameAndAgeJacksonComponent.Deserializer();
SimpleModule module = new SimpleModule();
module.addDeserializer(NameAndAge.class, deserializer);
ObjectMapper mapper = JsonMapper.builder().addModule(module).build();
JsonMapper mapper = JsonMapper.builder().addModule(module).build();
NameAndAge nameAndAge = mapper.readValue("{\"name\":\"spring\",\"age\":100}", NameAndAge.class);
assertThat(nameAndAge.getName()).isEqualTo("spring");
assertThat(nameAndAge.getAge()).isEqualTo(100);
@@ -25,7 +25,7 @@ import okhttp3.mockwebserver.MockWebServer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientProperties.Provider;
import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientProperties.Registration;
@@ -328,7 +328,7 @@ class OAuth2ClientPropertiesMapperTests {
private void setupMockResponse(String issuer) {
MockResponse mockResponse = new MockResponse().setResponseCode(HttpStatus.OK.value())
.setBody(new ObjectMapper().writeValueAsString(getResponse(issuer)))
.setBody(new JsonMapper().writeValueAsString(getResponse(issuer)))
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
assertThat(this.server).isNotNull();
this.server.enqueue(mockResponse);
@@ -46,7 +46,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.mockito.InOrder;
import reactor.core.publisher.Mono;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.security.autoconfigure.actuate.web.reactive.ReactiveManagementWebSecurityAutoConfiguration;
@@ -773,7 +773,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests {
private void setupMockResponse(String issuer) {
MockResponse mockResponse = new MockResponse().setResponseCode(HttpStatus.OK.value())
.setBody(new ObjectMapper().writeValueAsString(getResponse(issuer)))
.setBody(new JsonMapper().writeValueAsString(getResponse(issuer)))
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
assertThat(this.server).isNotNull();
this.server.enqueue(mockResponse);
@@ -44,7 +44,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.mockito.InOrder;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.security.autoconfigure.SecurityAutoConfiguration;
@@ -761,7 +761,7 @@ class OAuth2ResourceServerAutoConfigurationTests {
private void setupMockResponse(String issuer) {
MockResponse mockResponse = new MockResponse().setResponseCode(HttpStatus.OK.value())
.setBody(new ObjectMapper().writeValueAsString(getResponse(issuer)))
.setBody(new JsonMapper().writeValueAsString(getResponse(issuer)))
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
assertThat(this.server).isNotNull();
this.server.enqueue(mockResponse);