Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit 3d46821

Browse files
authored
Use Jackson to get enum values (#206)
1 parent caa9239 commit 3d46821

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/constraints/ConstraintReaderImpl.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,61 @@
2020
package capital.scalable.restdocs.constraints;
2121

2222
import static capital.scalable.restdocs.constraints.ConstraintAndGroupDescriptionResolver.VALUE;
23-
import static capital.scalable.restdocs.constraints.MethodParameterValidatorConstraintResolver
24-
.CONSTRAINT_CLASS;
23+
import static capital.scalable.restdocs.constraints.MethodParameterValidatorConstraintResolver.CONSTRAINT_CLASS;
2524
import static capital.scalable.restdocs.i18n.SnippetTranslationResolver.translate;
26-
import static capital.scalable.restdocs.util.FormatUtil.arrayToString;
25+
import static capital.scalable.restdocs.util.FormatUtil.collectionToString;
2726
import static java.util.Collections.emptyList;
2827
import static java.util.Collections.singletonList;
2928
import static java.util.Collections.singletonMap;
3029
import static org.apache.commons.lang3.StringUtils.isBlank;
30+
import static org.slf4j.LoggerFactory.getLogger;
3131
import static org.springframework.util.ReflectionUtils.findField;
3232

3333
import java.lang.reflect.Field;
3434
import java.util.ArrayList;
3535
import java.util.Collections;
3636
import java.util.List;
3737

38+
import com.fasterxml.jackson.core.JsonProcessingException;
39+
import com.fasterxml.jackson.databind.ObjectMapper;
40+
import org.apache.commons.lang3.StringUtils;
41+
import org.slf4j.Logger;
3842
import org.springframework.core.MethodParameter;
3943
import org.springframework.restdocs.constraints.Constraint;
4044
import org.springframework.restdocs.constraints.ConstraintDescriptions;
4145
import org.springframework.restdocs.constraints.ResourceBundleConstraintDescriptionResolver;
4246

4347
public class ConstraintReaderImpl implements ConstraintReader {
4448

49+
private static final Logger log = getLogger(ConstraintReaderImpl.class);
50+
4551
private final ConstraintAndGroupDescriptionResolver constraintDescriptionResolver;
4652

4753
private final SkippableConstraintResolver skippableConstraintResolver;
4854

4955
private final MethodParameterConstraintResolver constraintResolver;
5056

51-
private ConstraintReaderImpl(MethodParameterConstraintResolver actualResolver) {
57+
private final ObjectMapper objectMapper;
58+
59+
private ConstraintReaderImpl(MethodParameterConstraintResolver actualResolver, ObjectMapper objectMapper) {
5260
constraintDescriptionResolver = new ConstraintAndGroupDescriptionResolver(
5361
new ResourceBundleConstraintDescriptionResolver());
5462
skippableConstraintResolver = new SkippableConstraintResolver(
5563
actualResolver, constraintDescriptionResolver);
5664
constraintResolver = new HumanReadableConstraintResolver(skippableConstraintResolver);
65+
this.objectMapper = objectMapper;
5766
}
5867

59-
public static ConstraintReaderImpl create() {
60-
return CONSTRAINT_CLASS != null ? createWithValidation() : createWithoutValidation();
68+
public static ConstraintReaderImpl create(ObjectMapper objectMapper) {
69+
return CONSTRAINT_CLASS != null ? createWithValidation(objectMapper) : createWithoutValidation(objectMapper);
6170
}
6271

63-
static ConstraintReaderImpl createWithoutValidation() {
64-
return new ConstraintReaderImpl(new NoOpMethodParameterConstraintResolver());
72+
static ConstraintReaderImpl createWithoutValidation(ObjectMapper objectMapper) {
73+
return new ConstraintReaderImpl(new NoOpMethodParameterConstraintResolver(), objectMapper);
6574
}
6675

67-
static ConstraintReaderImpl createWithValidation() {
68-
return new ConstraintReaderImpl(new MethodParameterValidatorConstraintResolver());
76+
static ConstraintReaderImpl createWithValidation(ObjectMapper objectMapper) {
77+
return new ConstraintReaderImpl(new MethodParameterValidatorConstraintResolver(), objectMapper);
6978
}
7079

7180
@Override
@@ -116,8 +125,20 @@ private List<String> getEnumConstraintMessage(Class<?> rawClass) {
116125
}
117126

118127
Class<Enum> enumClass = (Class<Enum>) rawClass;
128+
List<String> serializedEnumValues = new ArrayList<>();
129+
for (Enum e : enumClass.getEnumConstants()) {
130+
try {
131+
String jsonValue = objectMapper.writeValueAsString(e);
132+
// Result is wrapped in double quotes
133+
jsonValue = StringUtils.removeStart(jsonValue, "\"");
134+
jsonValue = StringUtils.removeEnd(jsonValue, "\"");
135+
serializedEnumValues.add(jsonValue);
136+
} catch (JsonProcessingException ex) {
137+
log.error("Failed to convert enum {}", e, ex);
138+
}
139+
}
119140

120-
String value = arrayToString(enumClass.getEnumConstants());
141+
String value = collectionToString(serializedEnumValues);
121142
String enumName = enumClass.getCanonicalName();
122143
String message = constraintDescriptionResolver.resolveDescription(
123144
new Constraint(enumName, singletonMap(VALUE, (Object) value)));

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/jackson/JacksonResultHandlers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void handle(MvcResult result) throws Exception {
5656
setObjectMapper(result.getRequest(), objectMapper);
5757
initRequestPattern(result.getRequest());
5858
setJavadocReader(result.getRequest(), JavadocReaderImpl.createWithSystemProperty());
59-
setConstraintReader(result.getRequest(), ConstraintReaderImpl.create());
59+
setConstraintReader(result.getRequest(), ConstraintReaderImpl.create(objectMapper));
6060
}
6161
}
6262
}

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/util/FormatUtil.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
import static org.apache.commons.lang3.StringUtils.isNotBlank;
2323
import static org.springframework.util.StringUtils.arrayToDelimitedString;
24+
import static org.springframework.util.StringUtils.collectionToDelimitedString;
25+
26+
import java.util.Collection;
2427

2528
public class FormatUtil {
2629
private FormatUtil() {
@@ -31,6 +34,10 @@ public static String arrayToString(Object[] o) {
3134
return "[" + arrayToDelimitedString(o, ", ") + "]";
3235
}
3336

37+
public static String collectionToString(Collection<?> c) {
38+
return "[" + collectionToDelimitedString(c, ", ") + "]";
39+
}
40+
3441
public static String addDot(String text) {
3542
return isNotBlank(text) && !text.endsWith(".") && !text.endsWith(" ")
3643
? text + "."

spring-auto-restdocs-core/src/test/java/capital/scalable/restdocs/constraints/ConstraintReaderImplTest.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import java.util.Collection;
3737
import java.util.List;
3838

39+
import com.fasterxml.jackson.annotation.JsonValue;
40+
import com.fasterxml.jackson.databind.ObjectMapper;
3941
import org.hibernate.validator.constraints.NotBlank;
4042
import org.hibernate.validator.constraints.NotEmpty;
4143
import org.junit.Test;
@@ -45,7 +47,7 @@ public class ConstraintReaderImplTest {
4547

4648
@Test
4749
public void getConstraintMessages() {
48-
ConstraintReader reader = createWithValidation();
50+
ConstraintReader reader = createWithValidation(new ObjectMapper());
4951

5052
List<String> messages = reader.getConstraintMessages(Constraintz.class, "name");
5153
assertThat(messages.size(), is(0));
@@ -93,11 +95,15 @@ public void getConstraintMessages() {
9395
messages = reader.getConstraintMessages(Constraintz.class, "enum2");
9496
assertThat(messages.size(), is(1));
9597
assertThat(messages.get(0), is("Custom enum description: [A, B]"));
98+
99+
messages = reader.getConstraintMessages(Constraintz.class, "enum3");
100+
assertThat(messages.size(), is(1));
101+
assertThat(messages.get(0), is("Must be one of [A first, B second]"));
96102
}
97103

98104
@Test
99105
public void getOptionalMessages() {
100-
ConstraintReader reader = createWithValidation();
106+
ConstraintReader reader = createWithValidation(new ObjectMapper());
101107

102108
List<String> messages = reader.getOptionalMessages(Constraintz.class, "name");
103109
assertThat(messages.size(), is(1));
@@ -143,7 +149,7 @@ public void getOptionalMessages() {
143149

144150
@Test
145151
public void getParameterConstraintMessages() throws NoSuchMethodException {
146-
ConstraintReader reader = createWithValidation();
152+
ConstraintReader reader = createWithValidation(new ObjectMapper());
147153

148154
Method method = MethodTest.class.getMethod("exec", Integer.class, String.class,
149155
Enum1.class);
@@ -164,19 +170,19 @@ public void getParameterConstraintMessages() throws NoSuchMethodException {
164170

165171
@Test
166172
public void getConstraintMessages_validationNotPresent() {
167-
ConstraintReaderImpl reader = createWithoutValidation();
173+
ConstraintReaderImpl reader = createWithoutValidation(new ObjectMapper());
168174
assertThat(reader.getConstraintMessages(Constraintz.class, "index").size(), is(0));
169175
}
170176

171177
@Test
172178
public void getOptionalMessages_validationNotPresent() {
173-
ConstraintReaderImpl reader = createWithoutValidation();
179+
ConstraintReaderImpl reader = createWithoutValidation(new ObjectMapper());
174180
assertThat(reader.getOptionalMessages(Constraintz.class, "name").size(), is(0));
175181
}
176182

177183
@Test
178184
public void getParameterConstraintMessages_validationNotPresent() throws NoSuchMethodException {
179-
ConstraintReaderImpl reader = createWithoutValidation();
185+
ConstraintReaderImpl reader = createWithoutValidation(new ObjectMapper());
180186
Method method = MethodTest.class.getMethod("exec", Integer.class, String.class,
181187
Enum1.class);
182188
assertThat(reader.getConstraintMessages(new MethodParameter(method, 0)).size(), is(0));
@@ -220,12 +226,30 @@ static class Constraintz {
220226

221227
@NotNull
222228
private Enum2 enum2;
229+
230+
private Enum3 enum3;
223231
}
224232

225233
enum Enum1 {ONE, TWO}
226234

227235
enum Enum2 {A, B}
228236

237+
enum Enum3 {
238+
A("A first"),
239+
B("B second");
240+
241+
private String jsonValue;
242+
243+
Enum3(String jsonValue) {
244+
this.jsonValue = jsonValue;
245+
}
246+
247+
@JsonValue
248+
public String getJsonValue() {
249+
return jsonValue;
250+
}
251+
}
252+
229253
interface UnresolvedGroup {
230254
}
231255

spring-auto-restdocs-core/src/test/java/capital/scalable/restdocs/util/FormatUtilTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
package capital.scalable.restdocs.util;
2121

22+
import static java.util.Arrays.asList;
2223
import static org.hamcrest.CoreMatchers.is;
2324
import static org.hamcrest.CoreMatchers.nullValue;
2425
import static org.junit.Assert.assertThat;
@@ -27,12 +28,17 @@
2728

2829
public class FormatUtilTest {
2930
@Test
30-
public void arrayToString() throws Exception {
31+
public void arrayToString() {
3132
assertThat(FormatUtil.arrayToString(new Object[]{"1", 2, "3"}), is("[1, 2, 3]"));
3233
}
3334

3435
@Test
35-
public void addDot() throws Exception {
36+
public void collectionToString() {
37+
assertThat(FormatUtil.collectionToString(asList("1", 2, "3")), is("[1, 2, 3]"));
38+
}
39+
40+
@Test
41+
public void addDot() {
3642
assertThat(FormatUtil.addDot(null), is(nullValue()));
3743
assertThat(FormatUtil.addDot(""), is(""));
3844
assertThat(FormatUtil.addDot("."), is("."));
@@ -41,7 +47,7 @@ public void addDot() throws Exception {
4147
}
4248

4349
@Test
44-
public void join() throws Exception {
50+
public void join() {
4551
assertThat(FormatUtil.join(""), is(""));
4652
assertThat(FormatUtil.join(", "), is(""));
4753
assertThat(FormatUtil.join(", ", null, null), is(""));

0 commit comments

Comments
 (0)