An Avro 129 schema is a JSON document; later chapters reuse this one:
{
"type": "record", "name": "Order", "namespace": "com.example.booknest",
"doc": "One BookNest sample order (version 1)",
"fields": [
{"name": "order_id", "type": "long"},
{"name": "customer_id", "type": "int"},
{"name": "order_ts", "type": {"type": "long", "logicalType": "timestamp-millis"}},
{"name": "channel",
"type": {"type": "enum", "name": "Channel", "symbols": ["ios", "android", "web"]}},
{"name": "status", "type": "string"},
{"name": "currency", "type": "string"},
{"name": "items", "type": {"type": "array", "items": {
"type": "record", "name": "Item", "fields": [
{"name": "book_id", "type": "int"},
{"name": "qty", "type": "int"},
{"name": "unit_price", "type": {"type": "bytes", "logicalType": "decimal",
"precision": 7, "scale": 2}}]}}},
{"name": "coupon", "type": ["null", "string"], "default": null},
{"name": "discount",
"type": {"type": "bytes", "logicalType": "decimal", "precision": 9, "scale": 2}},
{"name": "total",
"type": {"type": "bytes", "logicalType": "decimal", "precision": 9, "scale": 2}}
]
}Avro has eight primitive types, six complex ones (record, enum, array, map, union, fixed) and logical types such as decimal, uuid, date and timestamps in millis, micros or nanos. A union lists branches: ["null", "string"] is a nullable string, and because a default must match the first branch, null comes first. A logical type annotates a primitive: timestamp-millis is a long of epoch milliseconds, and decimal stores an unscaled integer in bytes, so 40.20 travels as 4020 with scale 2, which cures the binary-float money of Numbers and Precision. A reader that ignores a logical type sees the underlying primitive.