@@ -89,29 +89,30 @@ private Schema.Field lowercaseField(Schema.Field field, Schema schema) {
8989 * Recursively lowercases field names within default values based on the schema structure.
9090 * This handles complex types like records, maps, and arrays where field names appear in default values.
9191 *
92- * @param defaultValue The original default value (can be null, primitive, Map, List, etc.)
93- * @param schema The schema that describes the structure of this default value
92+ * @param fieldDefaultValue The original default value for a field (can be null, primitive, Map, List, etc.)
93+ * @param fieldSchema The schema that describes the structure of this field's default value
9494 * @return The default value with all field names lowercased
9595 */
9696 @ SuppressWarnings ("unchecked" )
97- private Object lowercaseDefaultValue (Object defaultValue , Schema schema ) {
98- if (defaultValue == null ) {
97+ private Object lowercaseDefaultValue (Object fieldDefaultValue , Schema fieldSchema ) {
98+ if (fieldDefaultValue == null ) {
9999 return null ;
100100 }
101101
102- Schema actualSchema = schema ;
103-
104- // Handle union types - get the actual schema based on the default value type
105- if (schema .getType () == Schema .Type .UNION ) {
106- // For unions, the default value corresponds to the first type in the union
107- actualSchema = schema .getTypes ().get (0 );
102+ // Handle union types to get the actual schema for processing the default value
103+ // For nullable unions, extract the non-null type since we know defaultValue is non-null
104+ Schema actualSchema = SchemaUtilities .extractIfOption (fieldSchema );
105+ // If still a union after extracting nullable option (i.e., multi-type non-nullable union),
106+ // the default value corresponds to the first type per Avro specification
107+ if (actualSchema .getType () == Schema .Type .UNION ) {
108+ actualSchema = actualSchema .getTypes ().get (0 );
108109 }
109110
110111 switch (actualSchema .getType ()) {
111112 case RECORD :
112113 // For records, the default value can be either a Map or GenericData.Record
113- if (defaultValue instanceof GenericData .Record ) {
114- GenericData .Record record = (GenericData .Record ) defaultValue ;
114+ if (fieldDefaultValue instanceof GenericData .Record ) {
115+ GenericData .Record record = (GenericData .Record ) fieldDefaultValue ;
115116 return lowercaseRecordDefaultValue (actualSchema , lowercasedFieldName -> {
116117 // Find the matching field in the original record's schema (case-insensitive)
117118 Schema .Field originalField = record .getSchema ().getField (lowercasedFieldName );
@@ -125,21 +126,21 @@ private Object lowercaseDefaultValue(Object defaultValue, Schema schema) {
125126 }
126127 return originalField != null ? record .get (originalField .pos ()) : null ;
127128 });
128- } else if (defaultValue instanceof Map ) {
129- Map <?, ?> recordMap = (Map <?, ?>) defaultValue ;
129+ } else if (fieldDefaultValue instanceof Map ) {
130+ Map <?, ?> recordMap = (Map <?, ?>) fieldDefaultValue ;
130131 return lowercaseRecordDefaultValue (actualSchema , lowercasedFieldName -> {
131132 // Find the matching key in the original map (case-insensitive)
132133 String matchingKey = findMatchingKeyForLowercased (recordMap , lowercasedFieldName );
133134 return matchingKey != null ? recordMap .get (matchingKey ) : null ;
134135 });
135136 }
136137 // If neither Map nor GenericData.Record, return as-is
137- return defaultValue ;
138+ return fieldDefaultValue ;
138139
139140 case MAP :
140141 // For maps, lowercase the keys and recursively process values
141- if (defaultValue instanceof Map ) {
142- Map <?, ?> mapValue = (Map <?, ?>) defaultValue ; // Use wildcards to handle Utf8 keys
142+ if (fieldDefaultValue instanceof Map ) {
143+ Map <?, ?> mapValue = (Map <?, ?>) fieldDefaultValue ; // Use wildcards to handle Utf8 keys
143144 Map <String , Object > lowercasedMap = new LinkedHashMap <>();
144145 Schema valueSchema = actualSchema .getValueType ();
145146
@@ -151,19 +152,19 @@ private Object lowercaseDefaultValue(Object defaultValue, Schema schema) {
151152 }
152153 return lowercasedMap ;
153154 }
154- return defaultValue ;
155+ return fieldDefaultValue ;
155156
156157 case ARRAY :
157158 // For arrays, recursively process each element
158- if (defaultValue instanceof List ) {
159- List <Object > arrayValue = (List <Object >) defaultValue ;
159+ if (fieldDefaultValue instanceof List ) {
160+ List <Object > arrayValue = (List <Object >) fieldDefaultValue ;
160161 Schema elementSchema = actualSchema .getElementType ();
161162
162163 return arrayValue .stream ()
163164 .map (element -> lowercaseDefaultValue (element , elementSchema ))
164165 .collect (Collectors .toList ());
165166 }
166- return defaultValue ;
167+ return fieldDefaultValue ;
167168
168169 case NULL :
169170 case BOOLEAN :
@@ -177,7 +178,7 @@ private Object lowercaseDefaultValue(Object defaultValue, Schema schema) {
177178 case FIXED :
178179 default :
179180 // Primitive types and others: return as-is
180- return defaultValue ;
181+ return fieldDefaultValue ;
181182 }
182183 }
183184
0 commit comments