Skip to content

Commit 7094fd3

Browse files
authored
Support enum avro serialization with default value (#391)
1 parent 76243f8 commit 7094fd3

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,21 +264,29 @@ public static Schema parseJsonSchema(String json) {
264264
/**
265265
* Constructs a new enum schema
266266
*
267+
* @param intr Introspector to use to find default enum value
267268
* @param bean Enum type to use for name / description / namespace
268269
* @param values List of enum names
270+
*
269271
* @return An {@link org.apache.avro.Schema.Type#ENUM ENUM} schema.
270272
*/
271-
public static Schema createEnumSchema(BeanDescription bean, List<String> values)
273+
public static Schema createEnumSchema(AnnotationIntrospector intr,
274+
BeanDescription bean, List<String> values)
272275
{
273276
final JavaType enumType = bean.getType();
277+
@SuppressWarnings("unchecked")
278+
Class<Enum<?>> rawEnumClass = (Class<Enum<?>>) enumType.getRawClass();
279+
final Enum<?> defaultEnumValue = intr.findDefaultEnumValue(bean.getClassInfo(),
280+
rawEnumClass.getEnumConstants());
281+
final String namespace = getNamespace(enumType, bean.getClassInfo());
274282
final Schema avroSchema;
275-
276283
try {
277284
avroSchema = Schema.createEnum(
278285
getName(enumType),
279286
bean.findClassDescription(),
280-
getNamespace(enumType, bean.getClassInfo()),
281-
values);
287+
namespace,
288+
values,
289+
defaultEnumValue != null ? defaultEnumValue.toString() : null);
282290
} catch (SchemaParseException spe) {
283291
final String msg = String.format("Problem generating Avro `Schema` for Enum type %s: %s",
284292
ClassUtil.getTypeDescription(enumType), spe.getMessage());

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/EnumVisitor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public Schema builtAvroSchema() {
4141
}
4242

4343
BeanDescription bean = _provider.getConfig().introspectClassAnnotations(_type);
44-
Schema schema = AvroSchemaHelper.createEnumSchema(bean, new ArrayList<>(_enums));
44+
Schema schema = AvroSchemaHelper.createEnumSchema(_provider.getAnnotationIntrospector(),
45+
bean, new ArrayList<>(_enums));
4546
_schemas.addSchema(_type, schema);
4647
return schema;
4748
}

avro/src/test/java/com/fasterxml/jackson/dataformat/avro/AvroTestBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ public Image(String uri, String title, int w, int h, Size s)
244244
public void setSize(Size s) { _size = s; }
245245
}
246246

247+
// public because needed by "AvroAliasTest"
247248
public enum Size { SMALL, LARGE; }
248249

249250
/*

avro/src/test/java/com/fasterxml/jackson/dataformat/avro/EnumTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package com.fasterxml.jackson.dataformat.avro;
22

3+
import java.util.stream.Collectors;
4+
import java.util.stream.Stream;
5+
36
import org.junit.jupiter.api.Test;
47

8+
import org.apache.avro.Schema;
9+
import org.apache.avro.Schema.Type;
10+
11+
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
12+
import com.fasterxml.jackson.annotation.JsonProperty;
13+
import com.fasterxml.jackson.dataformat.avro.schema.AvroSchemaGenerator;
14+
515
import static org.junit.jupiter.api.Assertions.assertEquals;
616
import static org.junit.jupiter.api.Assertions.assertNotNull;
717

@@ -35,6 +45,19 @@ protected static class EmployeeStr {
3545
public String gender;
3646
}
3747

48+
protected enum ABC {
49+
A,
50+
B,
51+
@JsonEnumDefaultValue
52+
C;
53+
}
54+
55+
protected static class ABCDefaultClass {
56+
public String name;
57+
@JsonProperty(required = true)
58+
public ABC abc;
59+
}
60+
3861
private final AvroMapper MAPPER = newMapper();
3962

4063
@Test
@@ -127,4 +150,35 @@ public void test_avroSchemaWithString_fromStringValueToEnumValue() throws Except
127150
assertEquals(Gender.F, output.gender);
128151
}
129152

153+
// [dataformats-binary#388]: Default value for enums with class
154+
@Test
155+
public void testClassEnumWithDefault() throws Exception
156+
{
157+
AvroSchemaGenerator gen = new AvroSchemaGenerator();
158+
159+
MAPPER.acceptJsonFormatVisitor(ABCDefaultClass.class, gen);
160+
AvroSchema schema = gen.getGeneratedSchema();
161+
assertNotNull(schema);
162+
163+
String json = schema.getAvroSchema().toString(true);
164+
assertNotNull(json);
165+
166+
// And read it back too just for fun
167+
AvroSchema s2 = MAPPER.schemaFrom(json);
168+
assertNotNull(s2);
169+
170+
Schema avroSchema = s2.getAvroSchema();
171+
172+
// String name, int value
173+
assertEquals(Type.RECORD, avroSchema.getType());
174+
Schema.Field f = avroSchema.getField("abc");
175+
assertNotNull(f);
176+
assertEquals("abc", f.name());
177+
178+
assertEquals(Type.ENUM, f.schema().getType());
179+
assertEquals(ABC.C.toString(), f.schema().getEnumDefault());
180+
assertEquals(Stream.of(ABC.values())
181+
.map(ABC::name)
182+
.collect(Collectors.toList()), f.schema().getEnumSymbols());
183+
}
130184
}

0 commit comments

Comments
 (0)