Browse Source

Upgrade to Jackson Bom 2.13.0

Closes gh-28298
pull/28308/head
Andy Wilkinson 4 years ago
parent
commit
84b553a8ca
  1. 52
      spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java
  2. 4
      spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java
  3. 15
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java
  4. 2
      spring-boot-project/spring-boot-dependencies/build.gradle
  5. 23
      spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterIntegrationTests.java

52
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java

@ -40,6 +40,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; @@ -40,6 +40,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerFactory;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
@ -155,7 +156,9 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -155,7 +156,9 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private ObjectMapper getObjectMapper() {
if (this.objectMapper == null) {
this.objectMapper = new ObjectMapper();
JsonMapper.Builder builder = JsonMapper.builder();
configureJsonMapper(builder);
this.objectMapper = builder.build();
configureObjectMapper(this.objectMapper);
}
return this.objectMapper;
@ -166,32 +169,47 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -166,32 +169,47 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
* {@link ConfigurationProperties @ConfigurationProperties} objects into a {@link Map}
* structure.
* @param mapper the object mapper
* @deprecated since 2.6 for removal in 2.8 in favor of
* {@link #configureJsonMapper(com.fasterxml.jackson.databind.json.JsonMapper.Builder)}
*/
@Deprecated
protected void configureObjectMapper(ObjectMapper mapper) {
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
mapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true);
mapper.setSerializationInclusion(Include.NON_NULL);
applyConfigurationPropertiesFilter(mapper);
applySerializationModifier(mapper);
mapper.registerModule(new JavaTimeModule());
}
private void applyConfigurationPropertiesFilter(ObjectMapper mapper) {
mapper.setAnnotationIntrospector(new ConfigurationPropertiesAnnotationIntrospector());
mapper.setFilterProvider(
}
/**
* Configure Jackson's {@link JsonMapper} to be used to serialize the
* {@link ConfigurationProperties @ConfigurationProperties} objects into a {@link Map}
* structure.
* @param builder the json mapper builder
* @since 2.6.0
*/
protected void configureJsonMapper(JsonMapper.Builder builder) {
builder.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
builder.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
builder.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
JsonMapper.builder();
builder.configure(MapperFeature.USE_STD_BEAN_NAMING, true);
builder.serializationInclusion(Include.NON_NULL);
applyConfigurationPropertiesFilter(builder);
applySerializationModifier(builder);
builder.addModule(new JavaTimeModule());
}
private void applyConfigurationPropertiesFilter(JsonMapper.Builder builder) {
builder.annotationIntrospector(new ConfigurationPropertiesAnnotationIntrospector());
builder.filterProvider(
new SimpleFilterProvider().setDefaultFilter(new ConfigurationPropertiesPropertyFilter()));
}
/**
* Ensure only bindable and non-cyclic bean properties are reported.
* @param mapper the object mapper
* @param builder the JsonMapper builder
*/
private void applySerializationModifier(ObjectMapper mapper) {
private void applySerializationModifier(JsonMapper.Builder builder) {
SerializerFactory factory = BeanSerializerFactory.instance
.withSerializerModifier(new GenericSerializerModifier());
mapper.setSerializerFactory(factory);
builder.serializerFactory(factory);
}
private ContextConfigurationProperties describeBeans(ObjectMapper mapper, ApplicationContext context,

4
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/CompositeHealthTests.java

@ -22,6 +22,7 @@ import java.util.Map; @@ -22,6 +22,7 @@ import java.util.Map;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.endpoint.ApiVersion;
@ -87,8 +88,7 @@ class CompositeHealthTests { @@ -87,8 +88,7 @@ class CompositeHealthTests {
components.put("db1", Health.up().build());
components.put("db2", Health.down().withDetail("a", "b").build());
CompositeHealth health = new CompositeHealth(ApiVersion.V2, Status.UP, components);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS);
JsonMapper mapper = JsonMapper.builder().disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS).build();
String json = mapper.writeValueAsString(health);
assertThat(json).isEqualTo("{\"status\":\"UP\",\"details\":{\"db1\":{\"status\":\"UP\"},"
+ "\"db2\":{\"status\":\"DOWN\",\"details\":{\"a\":\"b\"}}}}");

15
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java

@ -196,10 +196,11 @@ class JacksonAutoConfigurationTests { @@ -196,10 +196,11 @@ class JacksonAutoConfigurationTests {
.run((context) -> {
ObjectMapper mapper = context.getBean(ObjectMapper.class);
assertThat(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS.enabledByDefault()).isFalse();
assertThat(mapper.getSerializationConfig()
.hasMapperFeatures(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS.getMask())).isTrue();
assertThat(mapper.getDeserializationConfig()
.hasMapperFeatures(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS.getMask())).isTrue();
assertThat(mapper.getSerializationConfig().isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS))
.isTrue();
assertThat(mapper.getDeserializationConfig().isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS))
.isTrue();
});
}
@ -208,10 +209,8 @@ class JacksonAutoConfigurationTests { @@ -208,10 +209,8 @@ class JacksonAutoConfigurationTests {
this.contextRunner.withPropertyValues("spring.jackson.mapper.use_annotations:false").run((context) -> {
ObjectMapper mapper = context.getBean(ObjectMapper.class);
assertThat(MapperFeature.USE_ANNOTATIONS.enabledByDefault()).isTrue();
assertThat(mapper.getDeserializationConfig().hasMapperFeatures(MapperFeature.USE_ANNOTATIONS.getMask()))
.isFalse();
assertThat(mapper.getSerializationConfig().hasMapperFeatures(MapperFeature.USE_ANNOTATIONS.getMask()))
.isFalse();
assertThat(mapper.getDeserializationConfig().isEnabled(MapperFeature.USE_ANNOTATIONS)).isFalse();
assertThat(mapper.getSerializationConfig().isEnabled(MapperFeature.USE_ANNOTATIONS)).isFalse();
});
}

2
spring-boot-project/spring-boot-dependencies/build.gradle

@ -536,7 +536,7 @@ bom { @@ -536,7 +536,7 @@ bom {
]
}
}
library("Jackson Bom", "2.12.5") {
library("Jackson Bom", "2.13.0") {
group("com.fasterxml.jackson") {
imports = [
"jackson-bom"

23
spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/json/JacksonTesterIntegrationTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2021 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.
@ -24,7 +24,7 @@ import java.util.Map; @@ -24,7 +24,7 @@ import java.util.Map;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ByteArrayResource;
@ -50,24 +50,18 @@ class JacksonTesterIntegrationTests { @@ -50,24 +50,18 @@ class JacksonTesterIntegrationTests {
private JacksonTester<String> stringJson;
private ObjectMapper objectMapper;
private static final String JSON = "{\"name\":\"Spring\",\"age\":123}";
@BeforeEach
void setup() {
this.objectMapper = new ObjectMapper();
JacksonTester.initFields(this, this.objectMapper);
}
@Test
void typicalTest() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
String example = JSON;
assertThat(this.simpleJson.parse(example).getObject().getName()).isEqualTo("Spring");
}
@Test
void typicalListTest() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
String example = "[" + JSON + "]";
assertThat(this.listJson.parse(example)).asList().hasSize(1);
assertThat(this.listJson.parse(example).getObject().get(0).getName()).isEqualTo("Spring");
@ -75,6 +69,7 @@ class JacksonTesterIntegrationTests { @@ -75,6 +69,7 @@ class JacksonTesterIntegrationTests {
@Test
void typicalMapTest() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
Map<String, Integer> map = new LinkedHashMap<>();
map.put("a", 1);
map.put("b", 2);
@ -83,6 +78,7 @@ class JacksonTesterIntegrationTests { @@ -83,6 +78,7 @@ class JacksonTesterIntegrationTests {
@Test
void stringLiteral() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
String stringWithSpecialCharacters = "myString";
assertThat(this.stringJson.write(stringWithSpecialCharacters)).extractingJsonPathStringValue("@")
.isEqualTo(stringWithSpecialCharacters);
@ -90,6 +86,7 @@ class JacksonTesterIntegrationTests { @@ -90,6 +86,7 @@ class JacksonTesterIntegrationTests {
@Test
void parseSpecialCharactersTest() throws Exception {
JacksonTester.initFields(this, new ObjectMapper());
// Confirms that the handling of special characters is symmetrical between
// the serialization (via the JacksonTester) and the parsing (via json-path). By
// default json-path uses SimpleJson as its parser, which has a slightly different
@ -103,7 +100,7 @@ class JacksonTesterIntegrationTests { @@ -103,7 +100,7 @@ class JacksonTesterIntegrationTests {
@Test
void writeWithView() throws Exception {
this.objectMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
JacksonTester.initFields(this, JsonMapper.builder().disable(MapperFeature.DEFAULT_VIEW_INCLUSION).build());
ExampleObjectWithView object = new ExampleObjectWithView();
object.setName("Spring");
object.setAge(123);
@ -115,7 +112,7 @@ class JacksonTesterIntegrationTests { @@ -115,7 +112,7 @@ class JacksonTesterIntegrationTests {
@Test
void readWithResourceAndView() throws Exception {
this.objectMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
JacksonTester.initFields(this, JsonMapper.builder().disable(MapperFeature.DEFAULT_VIEW_INCLUSION).build());
ByteArrayResource resource = new ByteArrayResource(JSON.getBytes());
ObjectContent<ExampleObjectWithView> content = this.jsonWithView.forView(ExampleObjectWithView.TestView.class)
.read(resource);
@ -125,7 +122,7 @@ class JacksonTesterIntegrationTests { @@ -125,7 +122,7 @@ class JacksonTesterIntegrationTests {
@Test
void readWithReaderAndView() throws Exception {
this.objectMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
JacksonTester.initFields(this, JsonMapper.builder().disable(MapperFeature.DEFAULT_VIEW_INCLUSION).build());
Reader reader = new StringReader(JSON);
ObjectContent<ExampleObjectWithView> content = this.jsonWithView.forView(ExampleObjectWithView.TestView.class)
.read(reader);

Loading…
Cancel
Save