Skip to content

Commit d3d4641

Browse files
committed
Use Jackson 3 for JSON processing
Closes gh-974
1 parent 051870b commit d3d4641

File tree

16 files changed

+99
-106
lines changed

16 files changed

+99
-106
lines changed

spring-restdocs-core/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def jmustacheShadowJar = tasks.register("jmustacheShadowJar", ShadowJar) {
2828
dependencies {
2929
compileOnly("org.apiguardian:apiguardian-api")
3030

31-
implementation("com.fasterxml.jackson.core:jackson-databind")
31+
implementation("tools.jackson.core:jackson-databind")
3232
implementation("org.springframework:spring-web")
3333
implementation(files(jmustacheShadowJar))
3434

spring-restdocs-core/src/main/java/org/springframework/restdocs/hypermedia/AbstractJsonLinkExtractor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23-
import com.fasterxml.jackson.databind.ObjectMapper;
23+
import tools.jackson.databind.ObjectMapper;
2424

2525
import org.springframework.restdocs.operation.OperationResponse;
2626

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@
3434
import javax.xml.transform.sax.SAXSource;
3535
import javax.xml.transform.stream.StreamResult;
3636

37-
import com.fasterxml.jackson.databind.DeserializationFeature;
38-
import com.fasterxml.jackson.databind.ObjectMapper;
39-
import com.fasterxml.jackson.databind.SerializationFeature;
4037
import org.jspecify.annotations.Nullable;
4138
import org.xml.sax.ErrorHandler;
4239
import org.xml.sax.InputSource;
4340
import org.xml.sax.SAXException;
4441
import org.xml.sax.SAXParseException;
4542
import org.xml.sax.XMLReader;
43+
import tools.jackson.databind.ObjectMapper;
44+
import tools.jackson.databind.SerializationFeature;
45+
import tools.jackson.databind.json.JsonMapper;
4646

4747
import org.springframework.http.MediaType;
4848

@@ -142,8 +142,9 @@ public void fatalError(SAXParseException exception) throws SAXException {
142142

143143
private static final class JsonPrettyPrinter implements PrettyPrinter {
144144

145-
private final ObjectMapper objectMapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true)
146-
.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
145+
private final ObjectMapper objectMapper = JsonMapper.builder()
146+
.enable(SerializationFeature.INDENT_OUTPUT)
147+
.build();
147148

148149
@Override
149150
public byte[] prettyPrint(byte[] original) throws IOException {

spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@
1616

1717
package org.springframework.restdocs.payload;
1818

19-
import java.io.IOException;
2019
import java.util.Collections;
2120
import java.util.List;
2221
import java.util.Map;
2322
import java.util.Set;
2423
import java.util.TreeSet;
2524
import java.util.stream.Collectors;
2625

27-
import com.fasterxml.jackson.databind.ObjectMapper;
28-
import com.fasterxml.jackson.databind.SerializationFeature;
2926
import org.jspecify.annotations.Nullable;
27+
import tools.jackson.core.JacksonException;
28+
import tools.jackson.databind.ObjectMapper;
29+
import tools.jackson.databind.SerializationFeature;
30+
import tools.jackson.databind.json.JsonMapper;
3031

3132
import org.springframework.http.MediaType;
3233
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
@@ -44,8 +45,9 @@ public class FieldPathPayloadSubsectionExtractor
4445

4546
private static final ObjectMapper objectMapper = new ObjectMapper();
4647

47-
private static final ObjectMapper prettyPrintingOjectMapper = new ObjectMapper()
48-
.enable(SerializationFeature.INDENT_OUTPUT);
48+
private static final ObjectMapper prettyPrintingOjectMapper = JsonMapper.builder()
49+
.enable(SerializationFeature.INDENT_OUTPUT)
50+
.build();
4951

5052
private final String fieldPath;
5153

@@ -124,7 +126,7 @@ public byte[] extractSubsection(byte[] payload, @Nullable MediaType contentType,
124126
}
125127
return getObjectMapper(payload).writeValueAsBytes(value);
126128
}
127-
catch (IOException ex) {
129+
catch (JacksonException ex) {
128130
throw new PayloadHandlingException(ex);
129131
}
130132
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/JsonContentHandler.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616

1717
package org.springframework.restdocs.payload;
1818

19-
import java.io.IOException;
2019
import java.util.ArrayList;
2120
import java.util.Collection;
2221
import java.util.List;
2322
import java.util.Map;
2423

25-
import com.fasterxml.jackson.core.JsonProcessingException;
26-
import com.fasterxml.jackson.databind.ObjectMapper;
27-
import com.fasterxml.jackson.databind.SerializationFeature;
2824
import org.jspecify.annotations.Nullable;
25+
import tools.jackson.core.JacksonException;
26+
import tools.jackson.databind.ObjectMapper;
27+
import tools.jackson.databind.SerializationFeature;
28+
import tools.jackson.databind.json.JsonMapper;
2929

3030
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
3131

@@ -41,7 +41,7 @@ class JsonContentHandler implements ContentHandler {
4141

4242
private final JsonFieldTypesDiscoverer fieldTypesDiscoverer = new JsonFieldTypesDiscoverer();
4343

44-
private final ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
44+
private final ObjectMapper objectMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
4545

4646
private final byte[] rawContent;
4747

@@ -119,7 +119,7 @@ private boolean isEmptyCollection(Object value) {
119119
try {
120120
return this.objectMapper.writeValueAsString(content);
121121
}
122-
catch (JsonProcessingException ex) {
122+
catch (JacksonException ex) {
123123
throw new PayloadHandlingException(ex);
124124
}
125125
}
@@ -134,7 +134,7 @@ private Object readContent() {
134134
try {
135135
return new ObjectMapper().readValue(this.rawContent, Object.class);
136136
}
137-
catch (IOException ex) {
137+
catch (JacksonException ex) {
138138
throw new PayloadHandlingException(ex);
139139
}
140140
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/LinkMaskingContentModifierTests.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323
import java.util.Map;
2424

2525
import com.fasterxml.jackson.annotation.JsonProperty;
26-
import com.fasterxml.jackson.core.JsonProcessingException;
27-
import com.fasterxml.jackson.databind.ObjectMapper;
28-
import com.fasterxml.jackson.databind.SerializationFeature;
2926
import org.junit.jupiter.api.Test;
27+
import tools.jackson.core.JacksonException;
28+
import tools.jackson.databind.ObjectMapper;
29+
import tools.jackson.databind.SerializationFeature;
30+
import tools.jackson.databind.json.JsonMapper;
3031

3132
import org.springframework.restdocs.hypermedia.Link;
3233

@@ -85,12 +86,14 @@ void maskCanUseUtf8Characters() throws Exception {
8586
.isEqualTo(formattedHalPayloadWithLinks(new Link("a", ellipsis), new Link("b", ellipsis)));
8687
}
8788

88-
private byte[] atomPayloadWithLinks(Link... links) throws JsonProcessingException {
89+
private byte[] atomPayloadWithLinks(Link... links) throws JacksonException {
8990
return new ObjectMapper().writeValueAsBytes(createAtomPayload(links));
9091
}
9192

92-
private byte[] formattedAtomPayloadWithLinks(Link... links) throws JsonProcessingException {
93-
return new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true)
93+
private byte[] formattedAtomPayloadWithLinks(Link... links) throws JacksonException {
94+
return JsonMapper.builder()
95+
.enable(SerializationFeature.INDENT_OUTPUT)
96+
.build()
9497
.writeValueAsBytes(createAtomPayload(links));
9598
}
9699

@@ -100,12 +103,14 @@ private AtomPayload createAtomPayload(Link... links) {
100103
return payload;
101104
}
102105

103-
private byte[] halPayloadWithLinks(Link... links) throws JsonProcessingException {
106+
private byte[] halPayloadWithLinks(Link... links) throws JacksonException {
104107
return new ObjectMapper().writeValueAsBytes(createHalPayload(links));
105108
}
106109

107-
private byte[] formattedHalPayloadWithLinks(Link... links) throws JsonProcessingException {
108-
return new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true)
110+
private byte[] formattedHalPayloadWithLinks(Link... links) throws JacksonException {
111+
return JsonMapper.builder()
112+
.enable(SerializationFeature.INDENT_OUTPUT)
113+
.build()
109114
.writeValueAsBytes(createHalPayload(links));
110115
}
111116

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import java.util.HashMap;
2020
import java.util.Map;
2121

22-
import com.fasterxml.jackson.databind.ObjectMapper;
2322
import org.junit.jupiter.api.Test;
2423
import org.junit.jupiter.api.extension.ExtendWith;
24+
import tools.jackson.databind.ObjectMapper;
2525

2626
import org.springframework.restdocs.testfixtures.jupiter.CapturedOutput;
2727
import org.springframework.restdocs.testfixtures.jupiter.OutputCaptureExtension;

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@
1616

1717
package org.springframework.restdocs.payload;
1818

19-
import java.io.IOException;
2019
import java.util.Arrays;
2120
import java.util.Map;
2221

23-
import com.fasterxml.jackson.core.JsonParseException;
24-
import com.fasterxml.jackson.core.JsonProcessingException;
25-
import com.fasterxml.jackson.databind.JsonMappingException;
26-
import com.fasterxml.jackson.databind.ObjectMapper;
27-
import com.fasterxml.jackson.databind.SerializationFeature;
2822
import org.junit.jupiter.api.Test;
23+
import tools.jackson.core.JacksonException;
24+
import tools.jackson.databind.ObjectMapper;
25+
import tools.jackson.databind.SerializationFeature;
26+
import tools.jackson.databind.json.JsonMapper;
2927

3028
import org.springframework.http.MediaType;
3129

@@ -42,7 +40,7 @@ class FieldPathPayloadSubsectionExtractorTests {
4240

4341
@Test
4442
@SuppressWarnings("unchecked")
45-
void extractMapSubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
43+
void extractMapSubsectionOfJsonMap() throws JacksonException {
4644
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.b")
4745
.extractSubsection("{\"a\":{\"b\":{\"c\":5}}}".getBytes(), MediaType.APPLICATION_JSON);
4846
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
@@ -52,7 +50,7 @@ void extractMapSubsectionOfJsonMap() throws JsonParseException, JsonMappingExcep
5250

5351
@Test
5452
@SuppressWarnings("unchecked")
55-
void extractSingleElementArraySubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
53+
void extractSingleElementArraySubsectionOfJsonMap() throws JacksonException {
5654
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[]")
5755
.extractSubsection("{\"a\":[{\"b\":5}]}".getBytes(), MediaType.APPLICATION_JSON);
5856
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
@@ -62,7 +60,7 @@ void extractSingleElementArraySubsectionOfJsonMap() throws JsonParseException, J
6260

6361
@Test
6462
@SuppressWarnings("unchecked")
65-
void extractMultiElementArraySubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
63+
void extractMultiElementArraySubsectionOfJsonMap() throws JacksonException {
6664
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a")
6765
.extractSubsection("{\"a\":[{\"b\":5},{\"b\":4}]}".getBytes(), MediaType.APPLICATION_JSON);
6866
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
@@ -72,8 +70,7 @@ void extractMultiElementArraySubsectionOfJsonMap() throws JsonParseException, Js
7270

7371
@Test
7472
@SuppressWarnings("unchecked")
75-
void extractMapSubsectionFromSingleElementArrayInAJsonMap()
76-
throws JsonParseException, JsonMappingException, IOException {
73+
void extractMapSubsectionFromSingleElementArrayInAJsonMap() throws JacksonException {
7774
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b")
7875
.extractSubsection("{\"a\":[{\"b\":{\"c\":5}}]}".getBytes(), MediaType.APPLICATION_JSON);
7976
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
@@ -83,8 +80,7 @@ void extractMapSubsectionFromSingleElementArrayInAJsonMap()
8380

8481
@Test
8582
@SuppressWarnings("unchecked")
86-
void extractMapSubsectionWithCommonStructureFromMultiElementArrayInAJsonMap()
87-
throws JsonParseException, JsonMappingException, IOException {
83+
void extractMapSubsectionWithCommonStructureFromMultiElementArrayInAJsonMap() throws JacksonException {
8884
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b")
8985
.extractSubsection("{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6}}]}".getBytes(), MediaType.APPLICATION_JSON);
9086
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
@@ -120,7 +116,7 @@ void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMapWhereAllSubs
120116
@Test
121117
@SuppressWarnings("unchecked")
122118
void extractMapSubsectionWithVaryingStructureDueToOptionalFieldsFromMultiElementArrayInAJsonMap()
123-
throws JsonParseException, JsonMappingException, IOException {
119+
throws JacksonException {
124120
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b").extractSubsection(
125121
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": 7}}]}".getBytes(), MediaType.APPLICATION_JSON,
126122
Arrays.asList(new FieldDescriptor("d").optional()));
@@ -132,7 +128,7 @@ void extractMapSubsectionWithVaryingStructureDueToOptionalFieldsFromMultiElement
132128
@Test
133129
@SuppressWarnings("unchecked")
134130
void extractMapSubsectionWithVaryingStructureDueToOptionalParentFieldsFromMultiElementArrayInAJsonMap()
135-
throws JsonParseException, JsonMappingException, IOException {
131+
throws JacksonException {
136132
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b").extractSubsection(
137133
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": { \"e\": 7}}}]}".getBytes(),
138134
MediaType.APPLICATION_JSON, Arrays.asList(new FieldDescriptor("d").optional()));
@@ -142,9 +138,8 @@ void extractMapSubsectionWithVaryingStructureDueToOptionalParentFieldsFromMultiE
142138
}
143139

144140
@Test
145-
void extractedSubsectionIsPrettyPrintedWhenInputIsPrettyPrinted()
146-
throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
147-
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
141+
void extractedSubsectionIsPrettyPrintedWhenInputIsPrettyPrinted() throws JacksonException {
142+
ObjectMapper objectMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
148143
byte[] prettyPrintedPayload = objectMapper
149144
.writeValueAsBytes(objectMapper.readValue("{\"a\": { \"b\": { \"c\": 1 }}}", Object.class));
150145
byte[] extractedSubsection = new FieldPathPayloadSubsectionExtractor("a.b")
@@ -155,8 +150,7 @@ void extractedSubsectionIsPrettyPrintedWhenInputIsPrettyPrinted()
155150
}
156151

157152
@Test
158-
void extractedSubsectionIsNotPrettyPrintedWhenInputIsNotPrettyPrinted()
159-
throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
153+
void extractedSubsectionIsNotPrettyPrintedWhenInputIsNotPrettyPrinted() throws JacksonException {
160154
ObjectMapper objectMapper = new ObjectMapper();
161155
byte[] payload = objectMapper
162156
.writeValueAsBytes(objectMapper.readValue("{\"a\": { \"b\": { \"c\": 1 }}}", Object.class));
@@ -176,8 +170,8 @@ void extractNonExistentSubsection() {
176170

177171
@Test
178172
void extractEmptyArraySubsection() {
179-
assertThatThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a")
180-
.extractSubsection("{\"a\":[]}}".getBytes(), MediaType.APPLICATION_JSON))
173+
assertThatThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a").extractSubsection("{\"a\":[]}".getBytes(),
174+
MediaType.APPLICATION_JSON))
181175
.isInstanceOf(PayloadHandlingException.class)
182176
.hasMessage("a identifies an empty section of the payload");
183177
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonContentHandlerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void typeForFieldWithNullAndThenNotNullValueMustMatch() {
6060
@Test
6161
void typeForOptionalFieldWithNumberAndThenNullValueIsNumber() {
6262
FieldDescriptor descriptor = new FieldDescriptor("a[].id").optional();
63-
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(),
63+
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes(),
6464
Arrays.asList(descriptor))
6565
.resolveFieldType(descriptor);
6666
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.NUMBER);
@@ -78,7 +78,7 @@ void typeForOptionalFieldWithNullAndThenNumberIsNumber() {
7878
@Test
7979
void typeForFieldWithNumberAndThenNullValueIsVaries() {
8080
FieldDescriptor descriptor = new FieldDescriptor("a[].id");
81-
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(),
81+
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes(),
8282
Arrays.asList(descriptor))
8383
.resolveFieldType(descriptor);
8484
assertThat((JsonFieldType) fieldType).isEqualTo(JsonFieldType.VARIES);

spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/JsonFieldPathsTests.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616

1717
package org.springframework.restdocs.payload;
1818

19-
import java.io.IOException;
2019
import java.util.Arrays;
2120

22-
import com.fasterxml.jackson.databind.ObjectMapper;
2321
import org.junit.jupiter.api.Test;
22+
import tools.jackson.databind.ObjectMapper;
2423

2524
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
2625

@@ -99,12 +98,7 @@ void missingEntryBeneathNestedArrayIsIdentifiedAsUncommon() {
9998
}
10099

101100
private Object json(String json) {
102-
try {
103-
return new ObjectMapper().readValue(json, Object.class);
104-
}
105-
catch (IOException ex) {
106-
throw new RuntimeException(ex);
107-
}
101+
return new ObjectMapper().readValue(json, Object.class);
108102
}
109103

110104
}

0 commit comments

Comments
 (0)