@breadstone/ziegel-platform-serialization ​
Data serialization and media type formatting for the ziegel platform. Provides JSON and XML serialization, media type formatters, and comprehensive data transformation capabilities for enterprise applications.
Serialization: Enterprise data serialization with multiple formats, type safety, and comprehensive transformation capabilities.
🚀 Overview ​
@breadstone/ziegel-platform-serialization provides:
- Multiple Serializers: JSON and XML serialization with type safety
- Media Type Formatters: HTTP content type formatting and parsing
- String Serialization: Base serialization abstractions
- Format Support: Multiple serialization formats and MIME types
- Type Interfaces: Strongly typed serialization contracts
- Performance: Optimized serialization for enterprise applications
📦 Installation ​
npm install @breadstone/ziegel-platform-serialization
# or
yarn add @breadstone/ziegel-platform-serialization🧩 Features & Usage Examples ​
JSON Serialization ​
import { JsonSerializer, IJsonSerializer } from '@breadstone/ziegel-platform-serialization';
const jsonSerializer: IJsonSerializer = new JsonSerializer();
// Serialize objects to JSON
const data = {
id: 123,
name: 'John Doe',
createdAt: new Date(),
metadata: {
tags: ['user', 'premium'],
preferences: { theme: 'dark' }
}
};
const jsonString = jsonSerializer.serialize(data);
console.log(jsonString); // JSON string representation
// Deserialize from JSON
const deserializedData = jsonSerializer.deserialize<typeof data>(jsonString);
console.log(deserializedData); // Original object structureXML Serialization ​
import { XmlSerializer, IXmlSerializer } from '@breadstone/ziegel-platform-serialization';
const xmlSerializer: IXmlSerializer = new XmlSerializer();
// Serialize objects to XML
const userData = {
user: {
id: 123,
name: 'John Doe',
email: 'john@example.com',
profile: {
age: 30,
location: 'New York'
}
}
};
const xmlString = xmlSerializer.serialize(userData);
console.log(xmlString); // XML string representation
// Deserialize from XML
const deserializedUser = xmlSerializer.deserialize<typeof userData>(xmlString);
console.log(deserializedUser); // Original object structureMedia Type Formatting ​
import {
JsonMediaTypeFormatter,
XmlMediaTypeFormatter,
IMediaTypeFormatter
} from '@breadstone/ziegel-platform-serialization';
// JSON media type formatter
const jsonFormatter: IMediaTypeFormatter = new JsonMediaTypeFormatter();
// Format data for HTTP response
const responseData = { message: 'Success', data: userData };
const jsonResponse = jsonFormatter.format(responseData);
// Check supported media types
const isSupported = jsonFormatter.canFormat('application/json'); // true
// XML media type formatter
const xmlFormatter: IMediaTypeFormatter = new XmlMediaTypeFormatter();
const xmlResponse = xmlFormatter.format(responseData);
const supportsXml = xmlFormatter.canFormat('application/xml'); // trueCustom String Serializer ​
import { StringSerializer, IStringSerializer } from '@breadstone/ziegel-platform-serialization';
class CsvStringSerializer extends StringSerializer implements IStringSerializer {
serialize(data: any[]): string {
if (!Array.isArray(data) || data.length === 0) {
return '';
}
// Get headers from first object
const headers = Object.keys(data[0]);
const csvHeaders = headers.join(',');
// Convert data rows
const csvRows = data.map(row =>
headers.map(header => this.escapeValue(row[header])).join(',')
);
return [csvHeaders, ...csvRows].join('\n');
}
deserialize<T>(csvString: string): T[] {
const lines = csvString.split('\n').filter(line => line.trim());
if (lines.length < 2) return [] as T[];
const headers = lines[0].split(',');
const data = lines.slice(1).map(line => {
const values = line.split(',');
const obj: any = {};
headers.forEach((header, index) => {
obj[header] = this.parseValue(values[index]);
});
return obj;
});
return data as T[];
}
private escapeValue(value: any): string {
const stringValue = String(value ?? '');
if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n')) {
return `"${stringValue.replace(/"/g, '""')}"`;
}
return stringValue;
}
private parseValue(value: string): any {
// Remove quotes if present
if (value.startsWith('"') && value.endsWith('"')) {
value = value.slice(1, -1).replace(/""/g, '"');
}
// Try to parse as number
if (!isNaN(Number(value)) && value.trim() !== '') {
return Number(value);
}
// Try to parse as boolean
if (value.toLowerCase() === 'true') return true;
if (value.toLowerCase() === 'false') return false;
return value;
}
}
// Usage
const csvSerializer = new CsvStringSerializer();
const csvData = csvSerializer.serialize([
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
]);
console.log(csvData);Custom Media Type Formatter ​
import { MediaTypeFormatterBase, IMediaTypeFormatter } from '@breadstone/ziegel-platform-serialization';
class YamlMediaTypeFormatter extends MediaTypeFormatterBase implements IMediaTypeFormatter {
constructor() {
super(['application/yaml', 'text/yaml', 'application/x-yaml']);
}
format(data: any): string {
return this.convertToYaml(data);
}
parse<T>(content: string): T {
return this.parseYaml<T>(content);
}
private convertToYaml(obj: any, indent: number = 0): string {
const spaces = ' '.repeat(indent);
if (obj === null || obj === undefined) {
return 'null';
}
if (typeof obj === 'string') {
return `"${obj}"`;
}
if (typeof obj === 'number' || typeof obj === 'boolean') {
return String(obj);
}
if (Array.isArray(obj)) {
return obj.map(item => `${spaces}- ${this.convertToYaml(item, indent + 1)}`).join('\n');
}
if (typeof obj === 'object') {
return Object.entries(obj)
.map(([key, value]) => `${spaces}${key}: ${this.convertToYaml(value, indent + 1)}`)
.join('\n');
}
return String(obj);
}
private parseYaml<T>(yamlString: string): T {
// Simplified YAML parser (in real implementation, use a proper YAML parser)
try {
// This is a simplified implementation - use a proper YAML parser in production
return JSON.parse(yamlString) as T;
} catch {
throw new Error('Invalid YAML format');
}
}
}
// Register custom formatter
const yamlFormatter = new YamlMediaTypeFormatter();Serialization Format Enumeration ​
import { SerializationFormat } from '@breadstone/ziegel-platform-serialization';
// Use predefined formats
const formatType = SerializationFormat.JSON;
// Switch based on format
function getSerializer(format: SerializationFormat) {
switch (format) {
case SerializationFormat.JSON:
return new JsonSerializer();
case SerializationFormat.XML:
return new XmlSerializer();
default:
throw new Error(`Unsupported format: ${format}`);
}
}
// Serialize based on format
const serializer = getSerializer(SerializationFormat.JSON);
const result = serializer.serialize(data);HTTP Content Negotiation ​
import {
JsonMediaTypeFormatter,
XmlMediaTypeFormatter,
IMediaTypeFormatter
} from '@breadstone/ziegel-platform-serialization';
class ContentNegotiationService {
private formatters: Map<string, IMediaTypeFormatter> = new Map();
constructor() {
const jsonFormatter = new JsonMediaTypeFormatter();
const xmlFormatter = new XmlMediaTypeFormatter();
// Register formatters for all their supported media types
this.registerFormatter(jsonFormatter);
this.registerFormatter(xmlFormatter);
}
private registerFormatter(formatter: IMediaTypeFormatter): void {
const mediaTypes = formatter.getSupportedMediaTypes?.() || ['application/octet-stream'];
mediaTypes.forEach(mediaType => {
this.formatters.set(mediaType.toLowerCase(), formatter);
});
}
formatResponse(data: any, acceptHeader: string): { content: string; contentType: string } {
// Parse Accept header and find best match
const acceptedTypes = this.parseAcceptHeader(acceptHeader);
for (const mediaType of acceptedTypes) {
const formatter = this.formatters.get(mediaType.toLowerCase());
if (formatter) {
return {
content: formatter.format(data),
contentType: mediaType
};
}
}
// Default to JSON
const jsonFormatter = this.formatters.get('application/json')!;
return {
content: jsonFormatter.format(data),
contentType: 'application/json'
};
}
parseRequest<T>(content: string, contentType: string): T {
const formatter = this.formatters.get(contentType.toLowerCase());
if (!formatter) {
throw new Error(`Unsupported content type: ${contentType}`);
}
return formatter.parse<T>(content);
}
private parseAcceptHeader(acceptHeader: string): string[] {
return acceptHeader
.split(',')
.map(type => type.split(';')[0].trim())
.filter(type => type.length > 0);
}
}
// Usage in Express.js-like framework
const contentService = new ContentNegotiationService();
// Format response based on Accept header
const responseData = { message: 'Hello, World!', timestamp: new Date() };
const acceptHeader = 'application/xml, application/json;q=0.9, */*;q=0.8';
const response = contentService.formatResponse(responseData, acceptHeader);
console.log('Content-Type:', response.contentType);
console.log('Response:', response.content);📚 Package Exports ​
import {
// Core Serialization
ISerializer,
IStringSerializer,
StringSerializer,
// JSON Serialization
IJsonSerializer,
JsonSerializer,
// XML Serialization
IXmlSerializer,
XmlSerializer,
// Media Type Formatting
IMediaTypeFormatter,
MediaTypeFormatterBase,
JsonMediaTypeFormatter,
XmlMediaTypeFormatter,
// Serialization Formats
SerializationFormat
} from '@breadstone/ziegel-platform-serialization';🔧 Advanced Usage ​
Performance Optimized Serialization ​
class PerformanceJsonSerializer extends JsonSerializer {
private cache = new Map<string, any>();
serialize(data: any): string {
const cacheKey = this.generateCacheKey(data);
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const result = super.serialize(data);
// Cache serialized result
if (this.cache.size < 1000) { // Prevent memory leaks
this.cache.set(cacheKey, result);
}
return result;
}
private generateCacheKey(data: any): string {
// Simple cache key generation (in production, use a more sophisticated approach)
return JSON.stringify(data);
}
clearCache(): void {
this.cache.clear();
}
}Stream-Based Serialization ​
import { Transform } from 'stream';
class JsonStreamSerializer extends Transform {
private buffer = '';
_transform(chunk: any, encoding: BufferEncoding, callback: Function) {
try {
const serialized = JSON.stringify(chunk);
this.push(serialized + '\n');
callback();
} catch (error) {
callback(error);
}
}
}
class JsonStreamDeserializer extends Transform {
private buffer = '';
_transform(chunk: any, encoding: BufferEncoding, callback: Function) {
this.buffer += chunk.toString();
const lines = this.buffer.split('\n');
this.buffer = lines.pop() || ''; // Keep incomplete line in buffer
for (const line of lines) {
if (line.trim()) {
try {
const obj = JSON.parse(line);
this.push(obj);
} catch (error) {
callback(error);
return;
}
}
}
callback();
}
}📚 API Documentation ​
For detailed API documentation, visit: API Docs
Related Packages ​
- @breadstone/ziegel-platform: Core platform services
- @breadstone/ziegel-core: Foundation utilities
- @breadstone/ziegel-platform-http: HTTP services integration
License ​
MIT
Issues ​
Please report bugs and feature requests in the Issue Tracker
Part of the ziegel Enterprise TypeScript Framework includeMetadata: true, compression: 'gzip', encryption: { enabled: true, key: 'your-encryption-key' } };
const secureData = jsonSerializer.serialize(data, options);
### Binary Serialization
```typescript
import { MessagePackSerializer, ProtocolBufferSerializer } from '@ziegel/platform-serialization';
// MessagePack for efficient binary serialization
const msgPackSerializer = new MessagePackSerializer();
const binaryData = msgPackSerializer.serialize(data);
const restored = msgPackSerializer.deserialize(binaryData);
// Protocol Buffers for schema-based serialization
const protobufSerializer = new ProtocolBufferSerializer({
schemaPath: './schemas/user.proto'
});
const protoData = protobufSerializer.serialize(userData);Type-Safe Serialization ​
import { TypedSerializer, Schema } from '@ziegel/platform-serialization';
// Define data schema
interface User {
id: number;
name: string;
email: string;
createdAt: Date;
roles: string[];
}
const userSchema: Schema<User> = {
id: { type: 'number', required: true },
name: { type: 'string', required: true, maxLength: 100 },
email: { type: 'string', format: 'email' },
createdAt: { type: 'date' },
roles: { type: 'array', items: { type: 'string' } }
};
const typedSerializer = new TypedSerializer<User>(userSchema);
// Type-safe operations
const user: User = {
id: 1,
name: 'John',
email: 'john@example.com',
createdAt: new Date(),
roles: ['user', 'admin']
};
const serialized = typedSerializer.serialize(user); // Validated at runtime
const deserialized = typedSerializer.deserialize(serialized); // Strongly typedAdvanced Features ​
Custom Serializers ​
import { BaseSerializer, SerializationContext } from '@ziegel/platform-serialization';
class DateTimeSerializer extends BaseSerializer<Date> {
serialize(value: Date, context: SerializationContext): string {
return value.toISOString();
}
deserialize(data: string, context: SerializationContext): Date {
return new Date(data);
}
canHandle(value: any): value is Date {
return value instanceof Date;
}
}
// Register custom serializer
const serializer = new JsonSerializer();
serializer.registerCustom(Date, new DateTimeSerializer());Circular Reference Handling ​
import { CircularReferenceResolver } from '@ziegel/platform-serialization';
const resolver = new CircularReferenceResolver();
// Create circular reference
const parent = { name: 'Parent', child: null };
const child = { name: 'Child', parent: parent };
parent.child = child;
// Serialize with circular reference resolution
const serialized = resolver.serialize(parent);
const restored = resolver.deserialize(serialized);
// Circular references are properly restoredStreaming Serialization ​
import { StreamingSerializer } from '@ziegel/platform-serialization';
const streamingSerializer = new StreamingSerializer();
// Serialize large datasets in chunks
const largeDataset = generateLargeDataset(); // Millions of records
const stream = streamingSerializer.createSerializationStream({
chunkSize: 1000,
compression: true,
format: 'jsonl' // JSON Lines format
});
for (const chunk of largeDataset) {
await stream.write(chunk);
}
const result = await stream.finalize();Schema Evolution ​
import { SchemaEvolution, VersionedSerializer } from '@ziegel/platform-serialization';
// Define schema versions
const userSchemaV1 = {
version: 1,
fields: {
id: { type: 'number' },
name: { type: 'string' }
}
};
const userSchemaV2 = {
version: 2,
fields: {
id: { type: 'number' },
name: { type: 'string' },
email: { type: 'string', default: '' } // New field
}
};
// Setup schema evolution
const evolution = new SchemaEvolution();
evolution.addMigration(1, 2, (data) => ({
...data,
email: '' // Provide default for new field
}));
const versionedSerializer = new VersionedSerializer({
schemas: [userSchemaV1, userSchemaV2],
evolution: evolution,
currentVersion: 2
});
// Automatically handles version migration during deserialization
const oldData = versionedSerializer.deserialize(v1SerializedData);Performance Optimization ​
Compression ​
import { CompressionSerializer } from '@ziegel/platform-serialization';
const compressor = new CompressionSerializer({
algorithm: 'brotli', // 'gzip', 'deflate', 'lz4', 'brotli'
level: 6, // Compression level
threshold: 1024 // Only compress data > 1KB
});
// Automatic compression for large payloads
const compressed = compressor.serialize(largeData);
const decompressed = compressor.deserialize(compressed);Parallel Processing ​
import { ParallelSerializer } from '@ziegel/platform-serialization';
const parallelSerializer = new ParallelSerializer({
workers: 4, // Number of worker threads
chunkSize: 1000 // Items per chunk
});
// Serialize large arrays in parallel
const largeArray = new Array(100000).fill(0).map((_, i) => ({ id: i, data: `item-${i}` }));
const parallelResult = await parallelSerializer.serialize(largeArray);Caching and Memoization ​
import { CachedSerializer } from '@ziegel/platform-serialization';
const cachedSerializer = new CachedSerializer({
baseSerializer: jsonSerializer,
cacheSize: 1000,
ttl: 300000, // 5 minutes
keyGenerator: (data) => generateHash(data)
});
// Repeated serialization of identical data uses cache
const result1 = cachedSerializer.serialize(data); // Computed
const result2 = cachedSerializer.serialize(data); // From cacheFormat-Specific Features ​
MessagePack Optimization ​
import { MessagePackSerializer } from '@ziegel/platform-serialization';
const msgPackOptimized = new MessagePackSerializer({
useFloat32: true, // Use 32-bit floats for smaller size
useBinaryString: true, // Optimize string encoding
extensionCodec: {
// Custom type extensions
0x01: {
encode: (value: Date) => Buffer.from(value.toISOString()),
decode: (buffer: Buffer) => new Date(buffer.toString())
}
}
});Protocol Buffers ​
import { ProtocolBufferSerializer } from '@ziegel/platform-serialization';
// Define .proto schema
const protoSchema = `
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
google.protobuf.Timestamp created_at = 5;
}
`;
const protobufSerializer = new ProtocolBufferSerializer({
schema: protoSchema,
messageName: 'User'
});
// Highly efficient binary serialization
const protoData = protobufSerializer.serialize(userData);CBOR (Concise Binary Object Representation) ​
import { CBORSerializer } from '@ziegel/platform-serialization';
const cborSerializer = new CBORSerializer({
useTaggedValues: true, // Support CBOR tags
replacer: (key, value) => {
// Custom value transformation
if (value instanceof Date) {
return { __type: 'Date', value: value.toISOString() };
}
return value;
}
});Data Validation ​
Schema Validation ​
import { ValidatingSerializer, ValidationRule } from '@ziegel/platform-serialization';
const validationRules: ValidationRule[] = [
{
field: 'email',
validator: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
message: 'Invalid email format'
},
{
field: 'age',
validator: (value) => value >= 0 && value <= 150,
message: 'Age must be between 0 and 150'
}
];
const validatingSerializer = new ValidatingSerializer({
baseSerializer: jsonSerializer,
rules: validationRules,
strictMode: true
});
// Throws validation error for invalid data
try {
const result = validatingSerializer.serialize({ email: 'invalid-email', age: -5 });
} catch (error) {
console.error('Validation failed:', error.message);
}Runtime Type Checking ​
import { TypeCheckingSerializer } from '@ziegel/platform-serialization';
const typeChecker = new TypeCheckingSerializer({
enforceTypes: true,
coerceTypes: false, // Don't automatically convert types
allowExtraFields: false
});
// Ensures data matches expected types
const checkedData = typeChecker.serialize(data, userSchema);Integration Examples ​
Database Integration ​
import { DatabaseSerializer } from '@ziegel/platform-serialization';
class UserRepository {
private serializer = new DatabaseSerializer({
format: 'json',
compression: true,
encryption: true
});
async save(user: User): Promise<void> {
const serialized = this.serializer.serialize(user);
await this.database.store(user.id, serialized);
}
async load(id: number): Promise<User> {
const serialized = await this.database.retrieve(id);
return this.serializer.deserialize(serialized);
}
}HTTP API Integration ​
import { HTTPSerializer } from '@ziegel/platform-serialization';
const httpSerializer = new HTTPSerializer({
contentType: 'application/json',
encoding: 'utf-8',
compression: 'gzip'
});
// Express middleware
app.use('/api', (req, res, next) => {
req.deserializedBody = httpSerializer.deserialize(req.body);
const originalSend = res.send;
res.send = function(data) {
const serialized = httpSerializer.serialize(data);
return originalSend.call(this, serialized);
};
next();
});WebSocket Integration ​
import { WebSocketSerializer } from '@ziegel/platform-serialization';
const wsSerializer = new WebSocketSerializer({
format: 'messagepack', // Binary format for efficiency
compression: true
});
// WebSocket message handling
websocket.on('message', (data) => {
const message = wsSerializer.deserialize(data);
handleMessage(message);
});
// Send serialized message
const message = { type: 'update', data: updates };
websocket.send(wsSerializer.serialize(message));Configuration ​
Serializer Configuration ​
interface SerializationConfig {
format: 'json' | 'messagepack' | 'protobuf' | 'cbor';
compression: {
enabled: boolean;
algorithm: 'gzip' | 'deflate' | 'brotli' | 'lz4';
level: number;
threshold: number;
};
encryption: {
enabled: boolean;
algorithm: 'aes-256-gcm' | 'aes-192-gcm' | 'chacha20-poly1305';
key: string;
};
validation: {
enabled: boolean;
strictMode: boolean;
schema?: Schema;
};
performance: {
enableCaching: boolean;
parallelProcessing: boolean;
streamingThreshold: number;
};
}Advanced Configuration ​
const config: SerializationConfig = {
format: 'messagepack',
compression: {
enabled: true,
algorithm: 'brotli',
level: 6,
threshold: 1024
},
encryption: {
enabled: true,
algorithm: 'aes-256-gcm',
key: process.env.SERIALIZATION_KEY
},
validation: {
enabled: true,
strictMode: false,
schema: userSchema
},
performance: {
enableCaching: true,
parallelProcessing: true,
streamingThreshold: 10000
}
};Error Handling ​
Serialization Errors ​
import { SerializationError, DeserializationError } from '@ziegel/platform-serialization';
try {
const serialized = serializer.serialize(data);
} catch (error) {
if (error instanceof SerializationError) {
console.error('Serialization failed:', error.message);
console.error('Failed at path:', error.path);
console.error('Original data:', error.data);
}
}
try {
const deserialized = serializer.deserialize(data);
} catch (error) {
if (error instanceof DeserializationError) {
console.error('Deserialization failed:', error.message);
console.error('Corrupted data:', error.corruptedData);
}
}Recovery Strategies ​
import { ErrorRecoverySerializer } from '@ziegel/platform-serialization';
const recoverySerializer = new ErrorRecoverySerializer({
baseSerializer: jsonSerializer,
fallbackStrategy: 'partial', // 'skip', 'partial', 'default'
onError: (error, context) => {
console.warn('Serialization error:', error);
// Log or handle error
}
});
// Continues processing even with some errors
const result = recoverySerializer.serialize(dataWithSomeInvalidFields);Best Practices ​
Performance Guidelines ​
// Use appropriate format for use case
const fastSerializer = new MessagePackSerializer(); // For speed
const compactSerializer = new ProtocolBufferSerializer(); // For size
const compatibleSerializer = new JsonSerializer(); // For compatibility
// Optimize for large datasets
const optimizedSerializer = new StreamingSerializer({
chunkSize: 1000,
compression: true,
parallel: true
});Security Considerations ​
// Always validate untrusted data
const secureSerializer = new ValidatingSerializer({
schema: trustedSchema,
strictMode: true,
sanitizeInput: true
});
// Use encryption for sensitive data
const encryptedSerializer = new EncryptedSerializer({
algorithm: 'aes-256-gcm',
key: secureRandomKey(),
authenticatedData: true
});Memory Management ​
// Use streaming for large datasets
if (data.length > LARGE_DATASET_THRESHOLD) {
return streamingSerializer.serialize(data);
} else {
return standardSerializer.serialize(data);
}
// Clean up resources
serializer.dispose();Migration Guide ​
From JSON.stringify ​
// Before
const serialized = JSON.stringify(data);
const deserialized = JSON.parse(serialized);
// After
import { JsonSerializer } from '@ziegel/platform-serialization';
const serializer = new JsonSerializer();
const serialized = serializer.serialize(data);
const deserialized = serializer.deserialize(serialized);From custom serialization ​
// Before (custom implementation)
function serialize(data) {
return Buffer.from(JSON.stringify(data)).toString('base64');
}
function deserialize(data) {
return JSON.parse(Buffer.from(data, 'base64').toString());
}
// After (ziegel-platform-serialization)
import { Base64JsonSerializer } from '@ziegel/platform-serialization';
const serializer = new Base64JsonSerializer();
const serialized = serializer.serialize(data);
const deserialized = serializer.deserialize(serialized);API Reference ​
For complete API documentation, see the API Reference.
Related Packages ​
ziegel-core- Core framework functionalityziegel-platform-http- HTTP communication