Skip to content

Commit e4ee046

Browse files
authored
Migrate from Jackson 2 to Jackson 3 (#1980)
Summary of changes: - Migrate documentation generation logic to Jackson 3. - Drop explicit exception handling in documentation generation logic. - Replace `JacksonRules` Refaster collection with Jackson 2 and Jackson 3 equivalents.
1 parent 5679391 commit e4ee046

File tree

12 files changed

+162
-64
lines changed

12 files changed

+162
-64
lines changed

documentation-support/pom.xml

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,6 @@
2828
<groupId>com.fasterxml.jackson.core</groupId>
2929
<artifactId>jackson-annotations</artifactId>
3030
</dependency>
31-
<dependency>
32-
<groupId>com.fasterxml.jackson.core</groupId>
33-
<artifactId>jackson-databind</artifactId>
34-
</dependency>
35-
<dependency>
36-
<groupId>com.fasterxml.jackson.datatype</groupId>
37-
<artifactId>jackson-datatype-guava</artifactId>
38-
</dependency>
39-
<dependency>
40-
<groupId>com.fasterxml.jackson.module</groupId>
41-
<artifactId>jackson-module-parameter-names</artifactId>
42-
</dependency>
4331
<dependency>
4432
<groupId>com.google.auto</groupId>
4533
<artifactId>auto-common</artifactId>
@@ -91,5 +79,13 @@
9179
<artifactId>junit-jupiter-params</artifactId>
9280
<scope>test</scope>
9381
</dependency>
82+
<dependency>
83+
<groupId>tools.jackson.core</groupId>
84+
<artifactId>jackson-databind</artifactId>
85+
</dependency>
86+
<dependency>
87+
<groupId>tools.jackson.datatype</groupId>
88+
<artifactId>jackson-datatype-guava</artifactId>
89+
</dependency>
9490
</dependencies>
9591
</project>
Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,24 @@
11
package tech.picnic.errorprone.documentation;
22

3-
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
4-
import com.fasterxml.jackson.annotation.PropertyAccessor;
5-
import com.fasterxml.jackson.databind.ObjectMapper;
6-
import com.fasterxml.jackson.datatype.guava.GuavaModule;
7-
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
8-
import com.google.errorprone.annotations.FormatMethod;
9-
import java.io.IOException;
10-
import java.io.UncheckedIOException;
113
import java.nio.file.Path;
4+
import tools.jackson.databind.json.JsonMapper;
5+
import tools.jackson.datatype.guava.GuavaModule;
126

137
/**
148
* Utility class that offers mutually consistent JSON serialization and deserialization operations,
159
* without further specifying the exact schema used.
1610
*/
1711
final class Json {
18-
private static final ObjectMapper OBJECT_MAPPER =
19-
new ObjectMapper()
20-
.setVisibility(PropertyAccessor.FIELD, Visibility.ANY)
21-
.registerModules(new GuavaModule(), new ParameterNamesModule());
12+
private static final JsonMapper JSON_MAPPER =
13+
JsonMapper.builder().addModule(new GuavaModule()).build();
2214

2315
private Json() {}
2416

2517
static <T> T read(Path path, Class<T> clazz) {
26-
try {
27-
return OBJECT_MAPPER.readValue(path.toFile(), clazz);
28-
} catch (IOException e) {
29-
throw failure(e, "Failure reading from '%s'", path);
30-
}
18+
return JSON_MAPPER.readValue(path.toFile(), clazz);
3119
}
3220

3321
static <T> void write(Path path, T object) {
34-
try {
35-
OBJECT_MAPPER.writeValue(path.toFile(), object);
36-
} catch (IOException e) {
37-
throw failure(e, "Failure writing to '%s'", path);
38-
}
39-
}
40-
41-
@FormatMethod
42-
private static UncheckedIOException failure(IOException cause, String format, Object... args) {
43-
return new UncheckedIOException(format.formatted(args), cause);
22+
JSON_MAPPER.writeValue(path.toFile(), object);
4423
}
4524
}

documentation-support/src/test/java/tech/picnic/errorprone/documentation/JsonTest.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22

33
import static java.nio.charset.StandardCharsets.UTF_8;
44
import static org.assertj.core.api.Assertions.assertThat;
5-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
65

7-
import java.io.FileNotFoundException;
86
import java.io.IOException;
9-
import java.io.UncheckedIOException;
107
import java.nio.file.Files;
118
import java.nio.file.Path;
129
import org.junit.jupiter.api.Test;
@@ -25,14 +22,6 @@ void write(@TempDir Path directory) {
2522
assertThat(file).content(UTF_8).isEqualTo(TEST_JSON);
2623
}
2724

28-
@Test
29-
void writeFailure(@TempDir Path directory) {
30-
assertThatThrownBy(() -> Json.write(directory, TEST_OBJECT))
31-
.isInstanceOf(UncheckedIOException.class)
32-
.hasMessageContaining("Failure writing to '%s'", directory)
33-
.hasCauseInstanceOf(FileNotFoundException.class);
34-
}
35-
3625
@Test
3726
void read(@TempDir Path directory) throws IOException {
3827
Path file = directory.resolve("test.json");
@@ -42,13 +31,5 @@ void read(@TempDir Path directory) throws IOException {
4231
assertThat(Json.read(file, TestObject.class)).isEqualTo(TEST_OBJECT);
4332
}
4433

45-
@Test
46-
void readFailure(@TempDir Path directory) {
47-
assertThatThrownBy(() -> Json.read(directory, TestObject.class))
48-
.isInstanceOf(UncheckedIOException.class)
49-
.hasMessageContaining("Failure reading from '%s'", directory)
50-
.hasCauseInstanceOf(FileNotFoundException.class);
51-
}
52-
5334
private record TestObject(String string, int number) {}
5435
}

error-prone-contrib/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@
288288
<artifactId>testng</artifactId>
289289
<scope>provided</scope>
290290
</dependency>
291+
<dependency>
292+
<groupId>tools.jackson.core</groupId>
293+
<artifactId>jackson-databind</artifactId>
294+
<scope>provided</scope>
295+
</dependency>
291296
</dependencies>
292297

293298
<build>

error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/JacksonRules.java renamed to error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/Jackson2Rules.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
import java.util.Optional;
1010
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
1111

12-
/** Refaster rules related to Jackson expressions and statements. */
12+
/** Refaster rules related to Jackson 2.x expressions and statements. */
1313
@OnlineDocumentation
14-
final class JacksonRules {
15-
private JacksonRules() {}
14+
final class Jackson2Rules {
15+
private Jackson2Rules() {}
1616

1717
/** Prefer {@link JsonNode#optional(int)} over more contrived alternatives. */
1818
static final class JsonNodeOptionalInt {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package tech.picnic.errorprone.refasterrules;
2+
3+
import com.google.errorprone.refaster.Refaster;
4+
import com.google.errorprone.refaster.annotation.AfterTemplate;
5+
import com.google.errorprone.refaster.annotation.BeforeTemplate;
6+
import java.util.Optional;
7+
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
8+
import tools.jackson.databind.JsonNode;
9+
import tools.jackson.databind.ObjectMapper;
10+
11+
/** Refaster rules related to Jackson 3.x expressions and statements. */
12+
@OnlineDocumentation
13+
final class Jackson3Rules {
14+
private Jackson3Rules() {}
15+
16+
/** Prefer {@link JsonNode#optional(int)} over more contrived alternatives. */
17+
static final class JsonNodeOptionalInt {
18+
@BeforeTemplate
19+
Optional<JsonNode> before(JsonNode node, int index) {
20+
return Refaster.anyOf(
21+
node.get(index).asOptional(),
22+
node.path(index).asOptional(),
23+
Optional.of(node.get(index)),
24+
Optional.ofNullable(node.get(index)));
25+
}
26+
27+
@AfterTemplate
28+
Optional<JsonNode> after(JsonNode node, int index) {
29+
return node.optional(index);
30+
}
31+
}
32+
33+
/** Prefer {@link JsonNode#optional(String)} over more contrived alternatives. */
34+
static final class JsonNodeOptionalString {
35+
@BeforeTemplate
36+
Optional<JsonNode> before(JsonNode node, String fieldName) {
37+
return Refaster.anyOf(
38+
node.get(fieldName).asOptional(),
39+
node.path(fieldName).asOptional(),
40+
Optional.of(node.get(fieldName)),
41+
Optional.ofNullable(node.get(fieldName)));
42+
}
43+
44+
@AfterTemplate
45+
Optional<JsonNode> after(JsonNode node, String fieldName) {
46+
return node.optional(fieldName);
47+
}
48+
}
49+
50+
/**
51+
* Prefer {@link ObjectMapper#valueToTree(Object)} over more contrived and less efficient
52+
* alternatives.
53+
*/
54+
static final class ObjectMapperValueToTree {
55+
@BeforeTemplate
56+
JsonNode before(ObjectMapper objectMapper, Object object) {
57+
return objectMapper.readTree(objectMapper.writeValueAsString(object));
58+
}
59+
60+
@AfterTemplate
61+
JsonNode after(ObjectMapper objectMapper, Object object) {
62+
return objectMapper.valueToTree(object);
63+
}
64+
}
65+
}

error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ final class RefasterRulesTest {
6464
ImmutableTableRules.class,
6565
InputStreamRules.class,
6666
IntStreamRules.class,
67-
JacksonRules.class,
67+
Jackson2Rules.class,
68+
Jackson3Rules.class,
6869
JUnitRules.class,
6970
JUnitToAssertJRules.class,
7071
LongStreamRules.class,

error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/JacksonRulesTestInput.java renamed to error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/Jackson2RulesTestInput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Optional;
99
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
1010

11-
final class JacksonRulesTest implements RefasterRuleCollectionTestCase {
11+
final class Jackson2RulesTest implements RefasterRuleCollectionTestCase {
1212
ImmutableSet<Optional<JsonNode>> testJsonNodeOptionalInt() {
1313
return ImmutableSet.of(
1414
NullNode.getInstance().get(1).asOptional(),

error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/JacksonRulesTestOutput.java renamed to error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/Jackson2RulesTestOutput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Optional;
99
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
1010

11-
final class JacksonRulesTest implements RefasterRuleCollectionTestCase {
11+
final class Jackson2RulesTest implements RefasterRuleCollectionTestCase {
1212
ImmutableSet<Optional<JsonNode>> testJsonNodeOptionalInt() {
1313
return ImmutableSet.of(
1414
NullNode.getInstance().optional(1),
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package tech.picnic.errorprone.refasterrules;
2+
3+
import com.google.common.collect.ImmutableSet;
4+
import java.util.Optional;
5+
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
6+
import tools.jackson.databind.JsonNode;
7+
import tools.jackson.databind.ObjectMapper;
8+
import tools.jackson.databind.node.NullNode;
9+
10+
final class Jackson3RulesTest implements RefasterRuleCollectionTestCase {
11+
ImmutableSet<Optional<JsonNode>> testJsonNodeOptionalInt() {
12+
return ImmutableSet.of(
13+
NullNode.getInstance().get(1).asOptional(),
14+
NullNode.getInstance().path(2).asOptional(),
15+
Optional.of(NullNode.getInstance().get(3)),
16+
Optional.ofNullable(NullNode.getInstance().get(4)));
17+
}
18+
19+
ImmutableSet<Optional<JsonNode>> testJsonNodeOptionalString() {
20+
return ImmutableSet.of(
21+
NullNode.getInstance().get("foo").asOptional(),
22+
NullNode.getInstance().path("bar").asOptional(),
23+
Optional.of(NullNode.getInstance().get("baz")),
24+
Optional.ofNullable(NullNode.getInstance().get("qux")));
25+
}
26+
27+
JsonNode testObjectMapperValueToTree() {
28+
return new ObjectMapper().readTree(new ObjectMapper().writeValueAsString("foo"));
29+
}
30+
}

0 commit comments

Comments
 (0)