Avsc - Avro for JavaScript
Avsc is a pure JavaScript implementation of the Apache Avro specification, currently stable at version 5.7.9. It provides fast and compact data serialization and deserialization, often outperforming JSON with smaller encodings. Key features include comprehensive support for Avro type inference, schema evolution, logical types (e.g., handling JavaScript Date objects transparently), and remote procedure calls (RPC) with IDL support. The library is actively maintained, with recent minor updates indicating ongoing development. It differentiates itself by offering a complete Avro ecosystem within JavaScript, making it suitable for high-performance data interchange and integration with Avro-based systems like Apache Kafka, especially in Node.js environments. The package also ships with built-in TypeScript type definitions.
Common errors
-
RangeError: Attempt to access memory outside buffer bounds
cause Attempting to decode a corrupted or malformed Avro buffer, or using a reader schema that is fundamentally incompatible with the writer's schema.fixVerify the integrity of the Avro binary data. Ensure the schema used for decoding (`reader's schema`) is compatible with the schema used for encoding (`writer's schema`). If reading from a file, check file corruption or incorrect file type. -
AvroTypeException: missing required field: 'fieldName'
cause A JavaScript object being encoded is missing a field that is defined as 'required' (non-nullable) in the Avro schema.fixEnsure that all non-nullable fields defined in your Avro schema are present in the JavaScript object you are attempting to serialize, or make the field nullable in the schema definition (e.g., `['null', 'string']`). -
TypeError: "type" must be a valid Avro type.
cause The schema provided to `Type.forSchema` is syntactically incorrect, incomplete, or contains invalid Avro type definitions.fixReview your Avro schema definition carefully against the Avro specification. Check for typos, missing `type` properties, incorrect capitalization of primitive types, or invalid complex type structures. -
Error: No matching type for schema 'avro.FullName'
cause Occurs during schema resolution for evolution, indicating a named type (e.g., a record, enum, or fixed type) referenced in the writer's or reader's schema cannot be found or resolved.fixEnsure all named types are fully defined or accessible within the context of the combined schemas when performing schema evolution. Check for correct namespaces and names of referenced types.
Warnings
- breaking Version 4.0.0 introduced a significant breaking change in how Avro unions are represented. Unions are now unwrapped by default, meaning they no longer use an encapsulating object for their value. This can affect code expecting the old wrapped structure.
- gotcha JavaScript's native `number` type is a 64-bit floating-point number, which can lead to precision loss for Avro's 64-bit integer (`long`) type if the values exceed `Number.MAX_SAFE_INTEGER` (2^53 - 1).
- gotcha The `avro.assemble` function for Avro IDL (AVDL) and JSON protocol (AVPR) import support, introduced in v3.3.0, does not fully support nested or external `import` statements within IDL files for schema parsing, unlike some other Avro implementations. This can complicate large, modular schema definitions.
- gotcha While `avsc` supports schema evolution, providing incompatible reader and writer schemas (e.g., removing required fields or changing fundamental types without a compatible evolution rule) will result in runtime errors during decoding.
Install
-
npm install avsc -
yarn add avsc -
pnpm add avsc
Imports
- avro
const avro = require('avsc');import * as avro from 'avsc';
- Type
import avro from 'avsc'; const type = avro.Type; // 'avro' is not the default export
import { Type } from 'avsc'; - Service
import avro from 'avsc'; const service = avro.Service; // 'avro' is not the default export
import { Service } from 'avsc'; - createFileDecoder
import avro from 'avsc'; const decoder = avro.createFileDecoder;
import { createFileDecoder } from 'avsc';
Quickstart
import { Type } from 'avsc';
const petSchema = {
type: 'record',
name: 'Pet',
fields: [
{
name: 'kind',
type: { type: 'enum', name: 'PetKind', symbols: ['CAT', 'DOG', 'FISH'] }
},
{ name: 'name', type: 'string' }
]
};
// Create an Avro Type from a schema definition
const petType = Type.forSchema(petSchema);
// Encode a JavaScript object into an Avro binary buffer
const myPet = { kind: 'CAT', name: 'Albert' };
const buf = petType.toBuffer(myPet);
console.log('Original object:', myPet);
console.log('Encoded buffer:', buf.toString('hex'));
// Decode the Avro binary buffer back into a JavaScript object
const decodedPet = petType.fromBuffer(buf);
console.log('Decoded object:', decodedPet);
// Example of schema inference for similar structures
const addressType = Type.forValue({
city: 'Cambridge',
zipCodes: ['02138', '02139'],
visits: 2
});
const otherAddress = { city: 'Seattle', zipCodes: ['98101'], visits: 3 };
const otherBuf = addressType.toBuffer(otherAddress);
console.log('\nInferred schema for:', otherAddress);
console.log('Encoded (inferred) buffer:', otherBuf.toString('hex'));