Skip to main content

Configuring Custom Types

Schemas can contain types that cannot be represented by Javascript primitive types, or where there's more than one possible type to deserialize into. For example, the Avro logical type timestamp-millis represents a date, but is serialized as a long. In order to deserialize that into a Date object, we need to configure the schema library.

Avro

@kafkajs/confluent-schema-registry uses the avsc library for Avro encoding/decoding. The Schema Type Options for Avro are passed to avsc.Type.forSchema, which allows us to set up a mapping between the logical type and the type we want to deserialize into:

import { SchemaRegistry, SchemaType } from '@kafkajs/confluent-schema-registry'
import avro from 'avsc'

class DateType extends avro.types.LogicalType {
_fromValue(val: string) {
return new Date(val);
}
_toValue(date: Date): number {
return +date
}
_resolve(type: any) {
if (avro.Type.isType(type, 'long', 'string', 'logical:timestamp-millis')) {
return this._fromValue;
}
}
}


const options = {
[SchemaType.AVRO]: {
logicalTypes: { 'timestamp-millis': DateType }
}
}
const registry = new SchemaRegistry({ host: 'http://localhost:9092' }, options)

Custom long type

JavaScript represents all numbers as doubles internally, which means that it is possible to lose precision when using very large numbers. In order to use a type that can accomodate such large numbers, you can use the same configuration option as above to have avsc use for example BigInt or longjs instead of the native number type.

See Custom Long Types for more details.