Apache Avro core components for data serialization with rich data structures, compact binary format, and schema evolution support
—
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.
Create schemas programmatically using static factory methods for all Avro types.
public static Schema create(Schema.Type type);
public static Schema createRecord(String name, String doc, String namespace, boolean isError, List<Schema.Field> fields);
public static Schema createEnum(String name, String doc, String namespace, List<String> values);
public static Schema createArray(Schema elementType);
public static Schema createMap(Schema valueType);
public static Schema createUnion(List<Schema> types);
public static Schema createFixed(String name, String doc, String namespace, int size);Usage Examples:
// Create primitive schemas
Schema stringSchema = Schema.create(Schema.Type.STRING);
Schema intSchema = Schema.create(Schema.Type.INT);
Schema nullSchema = Schema.create(Schema.Type.NULL);
// Create complex schemas
Schema arraySchema = Schema.createArray(Schema.create(Schema.Type.STRING));
Schema mapSchema = Schema.createMap(Schema.create(Schema.Type.INT));Parse schemas from JSON strings, files, or input streams using the Schema.Parser class.
public static class Parser {
public Schema parse(String jsonSchema) throws SchemaParseException;
public Schema parse(File file) throws IOException, SchemaParseException;
public Schema parse(InputStream in) throws IOException, SchemaParseException;
public Schema parse(String jsonSchema, boolean validate) throws SchemaParseException;
}Usage Examples:
// Parse schema from JSON string
String schemaJson = """
{
"type": "record",
"name": "User",
"namespace": "com.example",
"fields": [
{"name": "id", "type": "long"},
{"name": "name", "type": "string"},
{"name": "email", "type": ["null", "string"], "default": null}
]
}
""";
Schema schema = new Schema.Parser().parse(schemaJson);
// Parse schema from file
File schemaFile = new File("user.avsc");
Schema schema2 = new Schema.Parser().parse(schemaFile);
// Parse multiple schemas with cross-references
Schema.Parser parser = new Schema.Parser();
Schema dependencySchema = parser.parse(dependencyFile);
Schema mainSchema = parser.parse(mainSchemaFile);Use SchemaBuilder for programmatic schema construction with fluent API.
public class SchemaBuilder {
public static SchemaBuilder builder();
public static SchemaBuilder builder(String namespace);
public RecordBuilder record(String name);
public EnumBuilder enumeration(String name);
public ArrayBuilder array();
public MapBuilder map();
public UnionBuilder unionOf();
public FixedBuilder fixed(String name);
}
public interface RecordBuilder {
public FieldAssembler fields();
public RecordBuilder namespace(String namespace);
public RecordBuilder doc(String doc);
}
public interface FieldAssembler {
public FieldBuilder name(String fieldName);
public Schema endRecord();
}
public interface FieldBuilder {
public FieldTypeBuilder type();
public FieldBuilder doc(String doc);
public FieldBuilder withDefault(Object defaultVal);
public FieldBuilder noDefault();
}Usage Examples:
// Build record schema using fluent API
Schema userSchema = SchemaBuilder.builder()
.record("User")
.namespace("com.example")
.fields()
.name("id").type().longType().noDefault()
.name("name").type().stringType().noDefault()
.name("email").type().nullable().stringType().withDefault(null)
.name("age").type().intType().withDefault(0)
.endRecord();
// Build enum schema
Schema statusSchema = SchemaBuilder.builder()
.enumeration("Status")
.symbols("ACTIVE", "INACTIVE", "PENDING");
// Build array and map schemas
Schema stringArraySchema = SchemaBuilder.builder()
.array()
.items()
.stringType();
Schema intMapSchema = SchemaBuilder.builder()
.map()
.values()
.intType();Access schema metadata and structure information.
// Basic schema information
public Schema.Type getType();
public String getName();
public String getNamespace();
public String getFullName();
public String getDoc();
// Record-specific methods
public List<Schema.Field> getFields();
public Schema.Field getField(String fieldName);
public boolean hasField(String fieldName);
// Enum-specific methods
public List<String> getEnumSymbols();
public boolean hasEnumSymbol(String symbol);
public int getEnumOrdinal(String symbol);
// Array/Map-specific methods
public Schema getElementType(); // For arrays
public Schema getValueType(); // For maps
// Union-specific methods
public List<Schema> getTypes();
public int getIndexNamed(String name);
// Fixed-specific methods
public int getFixedSize();
// Logical type support
public LogicalType getLogicalType();
public void addProp(String name, String value);
public String getProp(String key);Usage Examples:
// Examine schema structure
Schema schema = new Schema.Parser().parse(schemaJson);
System.out.println("Schema type: " + schema.getType());
System.out.println("Schema name: " + schema.getName());
if (schema.getType() == Schema.Type.RECORD) {
for (Schema.Field field : schema.getFields()) {
System.out.println("Field: " + field.name() +
" Type: " + field.schema().getType());
}
}
// Check for specific fields
if (schema.hasField("email")) {
Schema.Field emailField = schema.getField("email");
System.out.println("Email field type: " + emailField.schema());
}Work with record field definitions including names, types, documentation, and default values.
public static class Field extends JsonProperties {
public Field(String name, Schema schema);
public Field(String name, Schema schema, String doc);
public Field(String name, Schema schema, String doc, Object defaultVal);
public Field(String name, Schema schema, String doc, Object defaultVal, Order order);
public String name();
public Schema schema();
public String doc();
public Object defaultVal();
public boolean hasDefaultValue();
public Order order();
public enum Order {
ASCENDING, DESCENDING, IGNORE
}
}Usage Examples:
// Create fields with different configurations
Schema.Field idField = new Schema.Field("id", Schema.create(Schema.Type.LONG), "User ID");
Schema.Field nameField = new Schema.Field("name", Schema.create(Schema.Type.STRING), "User name");
Schema.Field emailField = new Schema.Field("email",
Schema.createUnion(Arrays.asList(Schema.create(Schema.Type.NULL),
Schema.create(Schema.Type.STRING))),
"User email", null);
// Create record with fields
List<Schema.Field> fields = Arrays.asList(idField, nameField, emailField);
Schema recordSchema = Schema.createRecord("User", "User record", "com.example", false, fields);
// Examine field properties
for (Schema.Field field : recordSchema.getFields()) {
System.out.println("Field: " + field.name());
System.out.println("Has default: " + field.hasDefaultValue());
if (field.hasDefaultValue()) {
System.out.println("Default value: " + field.defaultVal());
}
}Extend Avro's type system with logical types for specialized data representations like decimals, dates, and timestamps.
public class LogicalTypes {
public static LogicalType decimal(int precision);
public static LogicalType decimal(int precision, int scale);
public static LogicalType uuid();
public static LogicalType date();
public static LogicalType timeMillis();
public static LogicalType timeMicros();
public static LogicalType timestampMillis();
public static LogicalType timestampMicros();
}
public abstract class LogicalType {
public abstract String getName();
public abstract void validate(Schema schema);
public abstract Object fromSchema(Schema schema);
}Usage Examples:
// Create schemas with logical types
Schema decimalSchema = LogicalTypes.decimal(10, 2).addToSchema(Schema.create(Schema.Type.BYTES));
Schema dateSchema = LogicalTypes.date().addToSchema(Schema.create(Schema.Type.INT));
Schema timestampSchema = LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG));
Schema uuidSchema = LogicalTypes.uuid().addToSchema(Schema.create(Schema.Type.STRING));
// Use in record schemas
Schema transactionSchema = SchemaBuilder.builder()
.record("Transaction")
.fields()
.name("id").type(uuidSchema).noDefault()
.name("amount").type(decimalSchema).noDefault()
.name("date").type(dateSchema).noDefault()
.name("timestamp").type(timestampSchema).noDefault()
.endRecord();
// Check for logical types
Schema schema = new Schema.Parser().parse(schemaJson);
for (Schema.Field field : schema.getFields()) {
LogicalType logicalType = field.schema().getLogicalType();
if (logicalType != null) {
System.out.println("Field " + field.name() + " has logical type: " + logicalType.getName());
}
}
// Using logical type conversions with GenericData
import org.apache.avro.Conversions;
import java.math.BigDecimal;
import java.util.UUID;
GenericData genericData = GenericData.get();
genericData.addLogicalTypeConversion(new Conversions.DecimalConversion());
genericData.addLogicalTypeConversion(new Conversions.UUIDConversion());
// Work with converted values in records
GenericRecord record = new GenericData.Record(transactionSchema);
record.put("id", UUID.randomUUID()); // UUID logical type
record.put("amount", new BigDecimal("123.45")); // Decimal logical typepublic abstract class Schema extends JsonProperties implements Serializable {
public enum Type {
RECORD, ENUM, ARRAY, MAP, UNION, FIXED, STRING, BYTES, INT, LONG, FLOAT, DOUBLE, BOOLEAN, NULL
}
public static class Field extends JsonProperties {
public enum Order { ASCENDING, DESCENDING, IGNORE }
}
public static class Parser {
public Parser();
public Parser(boolean validate);
}
}
public class SchemaBuilder {
public interface RecordBuilder extends NamedBuilder<Schema>;
public interface EnumBuilder extends NamedBuilder<Schema>;
public interface ArrayBuilder;
public interface MapBuilder;
public interface UnionBuilder;
public interface FixedBuilder extends NamedBuilder<Schema>;
}
public abstract class LogicalType {
// Base class for all logical type implementations
}
public class SchemaParseException extends AvroRuntimeException {
public SchemaParseException(String message);
public SchemaParseException(String message, Throwable cause);
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-avro--avro