11package com .fasterxml .jackson .dataformat .avro .schema ;
22
3- import com .fasterxml .jackson .databind .*;
3+ import java .util .ArrayList ;
4+ import java .util .List ;
5+
6+ import com .fasterxml .jackson .databind .BeanProperty ;
7+ import com .fasterxml .jackson .databind .JavaType ;
8+ import com .fasterxml .jackson .databind .JsonMappingException ;
9+ import com .fasterxml .jackson .databind .JsonSerializer ;
10+ import com .fasterxml .jackson .databind .SerializerProvider ;
11+ import com .fasterxml .jackson .databind .introspect .AnnotatedClass ;
412import com .fasterxml .jackson .databind .jsonFormatVisitors .JsonFormatVisitable ;
513import com .fasterxml .jackson .databind .jsonFormatVisitors .JsonObjectFormatVisitor ;
614import com .fasterxml .jackson .databind .ser .BeanPropertyWriter ;
715import com .fasterxml .jackson .dataformat .avro .AvroFixedSize ;
8- import org .apache .avro .Schema ;
916
10- import java . util . ArrayList ;
11- import java . util . List ;
17+ import org . apache . avro . Schema ;
18+ import org . apache . avro . reflect . AvroSchema ;
1219
1320public class RecordVisitor
1421 extends JsonObjectFormatVisitor .Base
@@ -19,6 +26,8 @@ public class RecordVisitor
1926 protected final DefinedSchemas _schemas ;
2027
2128 protected Schema _avroSchema ;
29+
30+ protected boolean _overridden ;
2231
2332 protected List <Schema .Field > _fields = new ArrayList <Schema .Field >();
2433
@@ -27,16 +36,27 @@ public RecordVisitor(SerializerProvider p, JavaType type, DefinedSchemas schemas
2736 super (p );
2837 _type = type ;
2938 _schemas = schemas ;
30- _avroSchema = Schema .createRecord (AvroSchemaHelper .getName (type ),
31- "Schema for " +type .toCanonical (),
32- AvroSchemaHelper .getNamespace (type ), false );
39+ // Check if the schema for this record is overridden
40+ AnnotatedClass ac = getProvider ().getConfig ().introspectDirectClassAnnotations (_type ).getClassInfo ();
41+ AvroSchema ann = ac .getAnnotation (AvroSchema .class );
42+ if (ann != null ) {
43+ Schema .Parser parser = new Schema .Parser ();
44+ _avroSchema = parser .parse (ann .value ());
45+ _overridden = true ;
46+ } else {
47+ String description = getProvider ().getAnnotationIntrospector ().findClassDescription (ac );
48+ _avroSchema = Schema .createRecord (AvroSchemaHelper .getName (type ), description , AvroSchemaHelper .getNamespace (type ), false );
49+ _overridden = false ;
50+ }
3351 schemas .addSchema (type , _avroSchema );
3452 }
3553
3654 @ Override
3755 public Schema builtAvroSchema () {
38- // Assumption now is that we are done, so let's assign fields
39- _avroSchema .setFields (_fields );
56+ if (!_overridden ) {
57+ // Assumption now is that we are done, so let's assign fields
58+ _avroSchema .setFields (_fields );
59+ }
4060 return _avroSchema ;
4161 }
4262
@@ -49,14 +69,19 @@ public Schema builtAvroSchema() {
4969 @ Override
5070 public void property (BeanProperty writer ) throws JsonMappingException
5171 {
52- Schema schema = schemaForWriter (writer );
53- _fields .add (new Schema .Field (writer .getName (), schema , null , null ));
72+ if (_overridden ) {
73+ return ;
74+ }
75+ _fields .add (schemaFieldForWriter (writer , false ));
5476 }
5577
5678 @ Override
5779 public void property (String name , JsonFormatVisitable handler ,
5880 JavaType type ) throws JsonMappingException
5981 {
82+ if (_overridden ) {
83+ return ;
84+ }
6085 VisitorFormatWrapperImpl wrapper = new VisitorFormatWrapperImpl (_schemas , getProvider ());
6186 handler .acceptJsonFormatVisitor (wrapper , type );
6287 Schema schema = wrapper .getAvroSchema ();
@@ -65,21 +90,19 @@ public void property(String name, JsonFormatVisitable handler,
6590
6691 @ Override
6792 public void optionalProperty (BeanProperty writer ) throws JsonMappingException {
68- Schema schema = schemaForWriter (writer );
69- /* 23-Nov-2012, tatu: Actually let's also assume that primitive type values
70- * are required, as Jackson does not distinguish whether optional has been
71- * defined, or is merely the default setting.
72- */
73- if (!writer .getType ().isPrimitive ()) {
74- schema = AvroSchemaHelper .unionWithNull (schema );
93+ if (_overridden ) {
94+ return ;
7595 }
76- _fields .add (new Schema . Field (writer . getName (), schema , null , null ));
96+ _fields .add (schemaFieldForWriter (writer , true ));
7797 }
7898
7999 @ Override
80100 public void optionalProperty (String name , JsonFormatVisitable handler ,
81101 JavaType type ) throws JsonMappingException
82102 {
103+ if (_overridden ) {
104+ return ;
105+ }
83106 VisitorFormatWrapperImpl wrapper = new VisitorFormatWrapperImpl (_schemas , getProvider ());
84107 handler .acceptJsonFormatVisitor (wrapper , type );
85108 Schema schema = wrapper .getAvroSchema ();
@@ -95,29 +118,47 @@ public void optionalProperty(String name, JsonFormatVisitable handler,
95118 /**********************************************************************
96119 */
97120
98- protected Schema schemaForWriter (BeanProperty prop ) throws JsonMappingException
121+ protected Schema . Field schemaFieldForWriter (BeanProperty prop , boolean optional ) throws JsonMappingException
99122 {
100- AvroFixedSize fixedSize = prop .getAnnotation (AvroFixedSize .class );
101- if (fixedSize != null ) {
102- return Schema .createFixed (fixedSize .typeName (), null , fixedSize .typeNamespace (), fixedSize .size ());
103- }
123+ Schema writerSchema ;
124+ // Check if schema for property is overridden
125+ AvroSchema schemaOverride = prop .getAnnotation (AvroSchema .class );
126+ if (schemaOverride != null ) {
127+ Schema .Parser parser = new Schema .Parser ();
128+ writerSchema = parser .parse (schemaOverride .value ());
129+ } else {
130+ AvroFixedSize fixedSize = prop .getAnnotation (AvroFixedSize .class );
131+ if (fixedSize != null ) {
132+ writerSchema = Schema .createFixed (fixedSize .typeName (), null , fixedSize .typeNamespace (), fixedSize .size ());
133+ } else {
134+ JsonSerializer <?> ser = null ;
104135
105- JsonSerializer <?> ser = null ;
136+ // 23-Nov-2012, tatu: Ideally shouldn't need to do this but...
137+ if (prop instanceof BeanPropertyWriter ) {
138+ BeanPropertyWriter bpw = (BeanPropertyWriter ) prop ;
139+ ser = bpw .getSerializer ();
140+ }
141+ final SerializerProvider prov = getProvider ();
142+ if (ser == null ) {
143+ if (prov == null ) {
144+ throw JsonMappingException .from (prov , "SerializerProvider missing for RecordVisitor" );
145+ }
146+ ser = prov .findValueSerializer (prop .getType (), prop );
147+ }
148+ VisitorFormatWrapperImpl visitor = new VisitorFormatWrapperImpl (_schemas , prov );
149+ ser .acceptJsonFormatVisitor (visitor , prop .getType ());
150+ writerSchema = visitor .getAvroSchema ();
151+ }
106152
107- // 23-Nov-2012, tatu: Ideally shouldn't need to do this but...
108- if (prop instanceof BeanPropertyWriter ) {
109- BeanPropertyWriter bpw = (BeanPropertyWriter ) prop ;
110- ser = bpw .getSerializer ();
111- }
112- final SerializerProvider prov = getProvider ();
113- if (ser == null ) {
114- if (prov == null ) {
115- throw JsonMappingException .from (prov , "SerializerProvider missing for RecordVisitor" );
153+ /* 23-Nov-2012, tatu: Actually let's also assume that primitive type values
154+ * are required, as Jackson does not distinguish whether optional has been
155+ * defined, or is merely the default setting.
156+ */
157+ if (optional && !prop .getType ().isPrimitive ()) {
158+ writerSchema = AvroSchemaHelper .unionWithNull (writerSchema );
116159 }
117- ser = prov .findValueSerializer (prop .getType (), prop );
118160 }
119- VisitorFormatWrapperImpl visitor = new VisitorFormatWrapperImpl (_schemas , prov );
120- ser .acceptJsonFormatVisitor (visitor , prop .getType ());
121- return visitor .getAvroSchema ();
161+ String description = getProvider ().getAnnotationIntrospector ().findPropertyDescription (prop .getMember ());
162+ return new Schema .Field (prop .getName (), writerSchema , description , null );
122163 }
123164}
0 commit comments