0
# Schema System
1
2
The Schema system forms the foundation of Apache Avro, providing JSON-based schema definitions that serve as contracts for data structure, validation, and evolution. Schemas define the structure of data and enable cross-language compatibility and schema evolution over time.
3
4
## Capabilities
5
6
### Schema Creation
7
8
Create schemas programmatically using static factory methods for all Avro types.
9
10
```java { .api }
11
public static Schema create(Schema.Type type);
12
public static Schema createRecord(String name, String doc, String namespace, boolean isError, List<Schema.Field> fields);
13
public static Schema createEnum(String name, String doc, String namespace, List<String> values);
14
public static Schema createArray(Schema elementType);
15
public static Schema createMap(Schema valueType);
16
public static Schema createUnion(List<Schema> types);
17
public static Schema createFixed(String name, String doc, String namespace, int size);
18
```
19
20
**Usage Examples:**
21
22
```java
23
// Create primitive schemas
24
Schema stringSchema = Schema.create(Schema.Type.STRING);
25
Schema intSchema = Schema.create(Schema.Type.INT);
26
Schema nullSchema = Schema.create(Schema.Type.NULL);
27
28
// Create complex schemas
29
Schema arraySchema = Schema.createArray(Schema.create(Schema.Type.STRING));
30
Schema mapSchema = Schema.createMap(Schema.create(Schema.Type.INT));
31
```
32
33
### Schema Parsing
34
35
Parse schemas from JSON strings, files, or input streams using the Schema.Parser class.
36
37
```java { .api }
38
public static class Parser {
39
public Schema parse(String jsonSchema) throws SchemaParseException;
40
public Schema parse(File file) throws IOException, SchemaParseException;
41
public Schema parse(InputStream in) throws IOException, SchemaParseException;
42
public Schema parse(String jsonSchema, boolean validate) throws SchemaParseException;
43
}
44
```
45
46
**Usage Examples:**
47
48
```java
49
// Parse schema from JSON string
50
String schemaJson = """
51
{
52
"type": "record",
53
"name": "User",
54
"namespace": "com.example",
55
"fields": [
56
{"name": "id", "type": "long"},
57
{"name": "name", "type": "string"},
58
{"name": "email", "type": ["null", "string"], "default": null}
59
]
60
}
61
""";
62
Schema schema = new Schema.Parser().parse(schemaJson);
63
64
// Parse schema from file
65
File schemaFile = new File("user.avsc");
66
Schema schema2 = new Schema.Parser().parse(schemaFile);
67
68
// Parse multiple schemas with cross-references
69
Schema.Parser parser = new Schema.Parser();
70
Schema dependencySchema = parser.parse(dependencyFile);
71
Schema mainSchema = parser.parse(mainSchemaFile);
72
```
73
74
### Fluent Schema Building
75
76
Use SchemaBuilder for programmatic schema construction with fluent API.
77
78
```java { .api }
79
public class SchemaBuilder {
80
public static SchemaBuilder builder();
81
public static SchemaBuilder builder(String namespace);
82
83
public RecordBuilder record(String name);
84
public EnumBuilder enumeration(String name);
85
public ArrayBuilder array();
86
public MapBuilder map();
87
public UnionBuilder unionOf();
88
public FixedBuilder fixed(String name);
89
}
90
91
public interface RecordBuilder {
92
public FieldAssembler fields();
93
public RecordBuilder namespace(String namespace);
94
public RecordBuilder doc(String doc);
95
}
96
97
public interface FieldAssembler {
98
public FieldBuilder name(String fieldName);
99
public Schema endRecord();
100
}
101
102
public interface FieldBuilder {
103
public FieldTypeBuilder type();
104
public FieldBuilder doc(String doc);
105
public FieldBuilder withDefault(Object defaultVal);
106
public FieldBuilder noDefault();
107
}
108
```
109
110
**Usage Examples:**
111
112
```java
113
// Build record schema using fluent API
114
Schema userSchema = SchemaBuilder.builder()
115
.record("User")
116
.namespace("com.example")
117
.fields()
118
.name("id").type().longType().noDefault()
119
.name("name").type().stringType().noDefault()
120
.name("email").type().nullable().stringType().withDefault(null)
121
.name("age").type().intType().withDefault(0)
122
.endRecord();
123
124
// Build enum schema
125
Schema statusSchema = SchemaBuilder.builder()
126
.enumeration("Status")
127
.symbols("ACTIVE", "INACTIVE", "PENDING");
128
129
// Build array and map schemas
130
Schema stringArraySchema = SchemaBuilder.builder()
131
.array()
132
.items()
133
.stringType();
134
135
Schema intMapSchema = SchemaBuilder.builder()
136
.map()
137
.values()
138
.intType();
139
```
140
141
### Schema Information Access
142
143
Access schema metadata and structure information.
144
145
```java { .api }
146
// Basic schema information
147
public Schema.Type getType();
148
public String getName();
149
public String getNamespace();
150
public String getFullName();
151
public String getDoc();
152
153
// Record-specific methods
154
public List<Schema.Field> getFields();
155
public Schema.Field getField(String fieldName);
156
public boolean hasField(String fieldName);
157
158
// Enum-specific methods
159
public List<String> getEnumSymbols();
160
public boolean hasEnumSymbol(String symbol);
161
public int getEnumOrdinal(String symbol);
162
163
// Array/Map-specific methods
164
public Schema getElementType(); // For arrays
165
public Schema getValueType(); // For maps
166
167
// Union-specific methods
168
public List<Schema> getTypes();
169
public int getIndexNamed(String name);
170
171
// Fixed-specific methods
172
public int getFixedSize();
173
174
// Logical type support
175
public LogicalType getLogicalType();
176
public void addProp(String name, String value);
177
public String getProp(String key);
178
```
179
180
**Usage Examples:**
181
182
```java
183
// Examine schema structure
184
Schema schema = new Schema.Parser().parse(schemaJson);
185
System.out.println("Schema type: " + schema.getType());
186
System.out.println("Schema name: " + schema.getName());
187
188
if (schema.getType() == Schema.Type.RECORD) {
189
for (Schema.Field field : schema.getFields()) {
190
System.out.println("Field: " + field.name() +
191
" Type: " + field.schema().getType());
192
}
193
}
194
195
// Check for specific fields
196
if (schema.hasField("email")) {
197
Schema.Field emailField = schema.getField("email");
198
System.out.println("Email field type: " + emailField.schema());
199
}
200
```
201
202
### Schema Fields
203
204
Work with record field definitions including names, types, documentation, and default values.
205
206
```java { .api }
207
public static class Field extends JsonProperties {
208
public Field(String name, Schema schema);
209
public Field(String name, Schema schema, String doc);
210
public Field(String name, Schema schema, String doc, Object defaultVal);
211
public Field(String name, Schema schema, String doc, Object defaultVal, Order order);
212
213
public String name();
214
public Schema schema();
215
public String doc();
216
public Object defaultVal();
217
public boolean hasDefaultValue();
218
public Order order();
219
220
public enum Order {
221
ASCENDING, DESCENDING, IGNORE
222
}
223
}
224
```
225
226
**Usage Examples:**
227
228
```java
229
// Create fields with different configurations
230
Schema.Field idField = new Schema.Field("id", Schema.create(Schema.Type.LONG), "User ID");
231
Schema.Field nameField = new Schema.Field("name", Schema.create(Schema.Type.STRING), "User name");
232
Schema.Field emailField = new Schema.Field("email",
233
Schema.createUnion(Arrays.asList(Schema.create(Schema.Type.NULL),
234
Schema.create(Schema.Type.STRING))),
235
"User email", null);
236
237
// Create record with fields
238
List<Schema.Field> fields = Arrays.asList(idField, nameField, emailField);
239
Schema recordSchema = Schema.createRecord("User", "User record", "com.example", false, fields);
240
241
// Examine field properties
242
for (Schema.Field field : recordSchema.getFields()) {
243
System.out.println("Field: " + field.name());
244
System.out.println("Has default: " + field.hasDefaultValue());
245
if (field.hasDefaultValue()) {
246
System.out.println("Default value: " + field.defaultVal());
247
}
248
}
249
```
250
251
### Logical Types
252
253
Extend Avro's type system with logical types for specialized data representations like decimals, dates, and timestamps.
254
255
```java { .api }
256
public class LogicalTypes {
257
public static LogicalType decimal(int precision);
258
public static LogicalType decimal(int precision, int scale);
259
public static LogicalType uuid();
260
public static LogicalType date();
261
public static LogicalType timeMillis();
262
public static LogicalType timeMicros();
263
public static LogicalType timestampMillis();
264
public static LogicalType timestampMicros();
265
}
266
267
public abstract class LogicalType {
268
public abstract String getName();
269
public abstract void validate(Schema schema);
270
public abstract Object fromSchema(Schema schema);
271
}
272
```
273
274
**Usage Examples:**
275
276
```java
277
// Create schemas with logical types
278
Schema decimalSchema = LogicalTypes.decimal(10, 2).addToSchema(Schema.create(Schema.Type.BYTES));
279
Schema dateSchema = LogicalTypes.date().addToSchema(Schema.create(Schema.Type.INT));
280
Schema timestampSchema = LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG));
281
Schema uuidSchema = LogicalTypes.uuid().addToSchema(Schema.create(Schema.Type.STRING));
282
283
// Use in record schemas
284
Schema transactionSchema = SchemaBuilder.builder()
285
.record("Transaction")
286
.fields()
287
.name("id").type(uuidSchema).noDefault()
288
.name("amount").type(decimalSchema).noDefault()
289
.name("date").type(dateSchema).noDefault()
290
.name("timestamp").type(timestampSchema).noDefault()
291
.endRecord();
292
293
// Check for logical types
294
Schema schema = new Schema.Parser().parse(schemaJson);
295
for (Schema.Field field : schema.getFields()) {
296
LogicalType logicalType = field.schema().getLogicalType();
297
if (logicalType != null) {
298
System.out.println("Field " + field.name() + " has logical type: " + logicalType.getName());
299
}
300
}
301
302
// Using logical type conversions with GenericData
303
import org.apache.avro.Conversions;
304
import java.math.BigDecimal;
305
import java.util.UUID;
306
307
GenericData genericData = GenericData.get();
308
genericData.addLogicalTypeConversion(new Conversions.DecimalConversion());
309
genericData.addLogicalTypeConversion(new Conversions.UUIDConversion());
310
311
// Work with converted values in records
312
GenericRecord record = new GenericData.Record(transactionSchema);
313
record.put("id", UUID.randomUUID()); // UUID logical type
314
record.put("amount", new BigDecimal("123.45")); // Decimal logical type
315
```
316
317
## Types
318
319
```java { .api }
320
public abstract class Schema extends JsonProperties implements Serializable {
321
public enum Type {
322
RECORD, ENUM, ARRAY, MAP, UNION, FIXED, STRING, BYTES, INT, LONG, FLOAT, DOUBLE, BOOLEAN, NULL
323
}
324
325
public static class Field extends JsonProperties {
326
public enum Order { ASCENDING, DESCENDING, IGNORE }
327
}
328
329
public static class Parser {
330
public Parser();
331
public Parser(boolean validate);
332
}
333
}
334
335
public class SchemaBuilder {
336
public interface RecordBuilder extends NamedBuilder<Schema>;
337
public interface EnumBuilder extends NamedBuilder<Schema>;
338
public interface ArrayBuilder;
339
public interface MapBuilder;
340
public interface UnionBuilder;
341
public interface FixedBuilder extends NamedBuilder<Schema>;
342
}
343
344
public abstract class LogicalType {
345
// Base class for all logical type implementations
346
}
347
348
public class SchemaParseException extends AvroRuntimeException {
349
public SchemaParseException(String message);
350
public SchemaParseException(String message, Throwable cause);
351
}
352
```