Skip to content

Commit a782d36

Browse files
committed
An improvement to schema-info handling for Enums with @JsonValue
1 parent 0e9d4dc commit a782d36

File tree

3 files changed

+96
-3
lines changed

3 files changed

+96
-3
lines changed

src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
175175
JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint);
176176
if (stringVisitor != null) {
177177
Set<String> enums = new LinkedHashSet<String>();
178-
178+
179179
// Use toString()?
180180
if ((serializers != null) &&
181181
serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {

src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java

+57-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
import java.lang.reflect.Method;
66
import java.lang.reflect.Modifier;
77
import java.lang.reflect.Type;
8+
import java.util.LinkedHashSet;
9+
import java.util.Set;
810

911
import com.fasterxml.jackson.core.*;
1012
import com.fasterxml.jackson.databind.*;
1113
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
1214
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
1315
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
16+
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
1417
import com.fasterxml.jackson.databind.jsonschema.SchemaAware;
1518
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
1619
import com.fasterxml.jackson.databind.ser.BeanSerializer;
@@ -246,19 +249,34 @@ public JsonNode getSchema(SerializerProvider provider, Type typeHint)
246249
}
247250
return com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
248251
}
249-
252+
250253
@Override
251254
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
252255
throws JsonMappingException
253256
{
257+
/* 27-Apr-2015, tatu: First things first; for JSON Schema introspection,
258+
* Enums are special, and unfortunately we will need to add special
259+
* handling here (see https://github.com/FasterXML/jackson-module-jsonSchema/issues/57
260+
* for details).
261+
*/
262+
Class<?> decl = (typeHint == null) ? null : typeHint.getRawClass();
263+
if (decl == null) {
264+
decl = _accessorMethod.getDeclaringClass();
265+
}
266+
if ((decl != null) && (decl.isEnum())) {
267+
if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, decl)) {
268+
return;
269+
}
270+
}
271+
254272
JsonSerializer<Object> ser = _valueSerializer;
255273
if (ser == null) {
256274
if (typeHint == null) {
257275
if (_property != null) {
258276
typeHint = _property.getType();
259277
}
260278
if (typeHint == null) {
261-
typeHint = visitor.getProvider().constructType(_accessorMethod.getReturnType());
279+
typeHint = visitor.getProvider().constructType(_handledType);
262280
}
263281
}
264282
ser = visitor.getProvider().findTypedValueSerializer(typeHint, false, _property);
@@ -270,6 +288,43 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
270288
ser.acceptJsonFormatVisitor(visitor, null);
271289
}
272290

291+
/**
292+
* Overridable helper method used for special case handling of schema information for
293+
* Enums
294+
*
295+
* @return True if method handled callbacks; false if not; in latter case caller will
296+
* send default callbacks
297+
*
298+
* @since 2.6
299+
*/
300+
protected boolean _acceptJsonFormatVisitorForEnum(JsonFormatVisitorWrapper visitor,
301+
JavaType typeHint, Class<?> enumType)
302+
throws JsonMappingException
303+
{
304+
// Copied from EnumSerializer#acceptJsonFormatVisitor
305+
JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint);
306+
if (stringVisitor != null) {
307+
Set<String> enums = new LinkedHashSet<String>();
308+
for (Object en : enumType.getEnumConstants()) {
309+
try {
310+
enums.add(String.valueOf(_accessorMethod.invoke(en)));
311+
} catch (Exception e) {
312+
Throwable t = e;
313+
while (t instanceof InvocationTargetException && t.getCause() != null) {
314+
t = t.getCause();
315+
}
316+
if (t instanceof Error) {
317+
throw (Error) t;
318+
}
319+
throw JsonMappingException.wrapWithPath(t, en, _accessorMethod.getName() + "()");
320+
}
321+
}
322+
stringVisitor.enumTypes(enums);
323+
}
324+
return true;
325+
326+
}
327+
273328
protected boolean isNaturalTypeWithStdHandling(Class<?> rawType, JsonSerializer<?> ser)
274329
{
275330
// First: do we have a natural type being handled?

src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java

+38
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.*;
44

5+
import com.fasterxml.jackson.annotation.JsonValue;
56
import com.fasterxml.jackson.databind.*;
67
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
78
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
@@ -22,6 +23,15 @@ public String toString() {
2223
}
2324
}
2425

26+
enum TestEnumWithJsonValue {
27+
A, B, C;
28+
29+
@JsonValue
30+
public String forSerialize() {
31+
return "value-"+name();
32+
}
33+
}
34+
2535
private final ObjectMapper MAPPER = new ObjectMapper();
2636

2737
public void testSimpleEnum() throws Exception
@@ -33,6 +43,7 @@ public void testSimpleEnum() throws Exception
3343
@Override
3444
public JsonStringFormatVisitor expectStringFormat(JavaType type) {
3545
return new JsonStringFormatVisitor() {
46+
@Override
3647
public void enumTypes(Set<String> enums) {
3748
values.addAll(enums);
3849
}
@@ -51,4 +62,31 @@ public void format(JsonValueFormat format) { }
5162
));
5263
assertEquals(exp, values);
5364
}
65+
66+
public void testEnumWithJsonValue() throws Exception
67+
{
68+
final Set<String> values = new TreeSet<String>();
69+
MAPPER.acceptJsonFormatVisitor(TestEnumWithJsonValue.class, new JsonFormatVisitorWrapper.Base() {
70+
@Override
71+
public JsonStringFormatVisitor expectStringFormat(JavaType type) {
72+
return new JsonStringFormatVisitor() {
73+
@Override
74+
public void enumTypes(Set<String> enums) {
75+
values.addAll(enums);
76+
}
77+
78+
@Override
79+
public void format(JsonValueFormat format) { }
80+
};
81+
}
82+
});
83+
84+
assertEquals(3, values.size());
85+
TreeSet<String> exp = new TreeSet<String>(Arrays.asList(
86+
"value-A",
87+
"value-B",
88+
"value-C"
89+
));
90+
assertEquals(exp, values);
91+
}
5492
}

0 commit comments

Comments
 (0)