MessagePack
Library
MessagePack
Overview
MessagePack is an efficient binary serialization format. While maintaining JSON-like ease of use, it achieves faster and more compact data representation. Implemented in over 50 languages with high portability, it's continuously chosen for use cases where data size reduction is important, such as IoT, mobile applications, and real-time communication. It plays a crucial role in modern applications requiring game development, microservices, and high-frequency data exchange.
Details
MessagePack 2025 version is a mature binary format that achieves 30-50% size reduction and over 10x processing speed improvement compared to JSON. It eliminates JSON format constraints, enabling direct storage of binary data, support for non-UTF-8 encoded strings, and arbitrary type map keys (including arrays and numbers). With proven adoption in large-scale services like Redis, Pinterest, and SignalR, its reliability in enterprise environments has been demonstrated.
Key Features
- Compactness: 30-50% smaller data size than JSON
- High Speed: Over 10x faster serialization/deserialization
- Multi-language Support: Implementation in 50+ languages with cross-platform compatibility
- Type Flexibility: Support for binary data, non-UTF-8 strings, and arbitrary type keys
- Proven Track Record: Adoption in large-scale services like Redis and Pinterest
- Standardization: Compatibility through clear specifications and multiple implementations
Pros and Cons
Pros
- Significant data size reduction (30-50%) and high-speed processing (10x+) compared to JSON
- High compatibility in multi-platform environments through implementation in 50+ languages
- No data representation constraints with direct support for binary data and non-UTF-8 strings
- Reduced battery consumption and data communication costs in IoT devices and mobile environments
- Proven performance in gaming, financial trading, and real-time communication
- Low learning cost for implementation due to simple specification
Cons
- Cannot be directly read/written by humans due to binary format
- Limited tool and editor support compared to JSON
- Requires decoding process to check data content during debugging
- Implementation-dependent limitations on array and integer sizes
- Some libraries have differences in functionality and optimization levels
- Limited compression effects for small data
Reference Pages
Code Examples
Basic Setup
# JavaScript/Node.js
npm install msgpack5
# or
npm install @msgpack/msgpack
# Python
pip install msgpack
# Java
# Maven
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.9.8</version>
</dependency>
# C# (.NET)
dotnet add package MessagePack
# Go
go get github.com/vmihailenco/msgpack/v5
# Rust
# Cargo.toml
[dependencies]
msgpack = "1.0"
Basic Usage in JavaScript/Node.js
// Using @msgpack/msgpack (recommended)
import { encode, decode } from '@msgpack/msgpack';
// Basic data structure
const userData = {
id: 123,
name: "John Doe",
email: "[email protected]",
tags: ["admin", "user"],
metadata: {
createdAt: new Date(),
isActive: true,
balance: 1234.56
}
};
// Encode (serialization)
const encoded = encode(userData);
console.log('Encoded size:', encoded.length, 'bytes');
console.log('Encoded data:', encoded);
// Decode (deserialization)
const decoded = decode(encoded);
console.log('Decoded data:', decoded);
// Size comparison with JSON
const jsonString = JSON.stringify(userData);
const jsonBytes = new TextEncoder().encode(jsonString);
console.log('JSON size:', jsonBytes.length, 'bytes');
console.log('MessagePack size:', encoded.length, 'bytes');
console.log('Size reduction:',
((jsonBytes.length - encoded.length) / jsonBytes.length * 100).toFixed(1), '%');
// Binary data processing
const binaryData = {
filename: "document.pdf",
content: new Uint8Array([0x25, 0x50, 0x44, 0x46]), // PDF header
metadata: {
size: 1024,
type: "application/pdf"
}
};
const encodedBinary = encode(binaryData);
const decodedBinary = decode(encodedBinary);
console.log('Binary data preserved:', decodedBinary);
// Array data processing
const timeSeriesData = [];
for (let i = 0; i < 1000; i++) {
timeSeriesData.push({
timestamp: Date.now() + i * 1000,
value: Math.random() * 100,
status: i % 10 === 0 ? 'alert' : 'normal'
});
}
const encodedTimeSeries = encode(timeSeriesData);
console.log('Time series data encoded:', encodedTimeSeries.length, 'bytes');
Advanced Usage in Python
import msgpack
import datetime
import numpy as np
from typing import Any, Dict, List
# Custom object serialization
class CustomObject:
def __init__(self, name: str, value: int):
self.name = name
self.value = value
self.created_at = datetime.datetime.now()
# Custom encoder
def custom_encoder(obj):
if isinstance(obj, CustomObject):
return {
'__type__': 'CustomObject',
'name': obj.name,
'value': obj.value,
'created_at': obj.created_at.isoformat()
}
elif isinstance(obj, datetime.datetime):
return {
'__type__': 'datetime',
'value': obj.isoformat()
}
elif isinstance(obj, np.ndarray):
return {
'__type__': 'numpy_array',
'dtype': str(obj.dtype),
'shape': obj.shape,
'data': obj.tobytes()
}
raise TypeError(f"Object of type {type(obj)} is not MessagePack serializable")
# Custom decoder
def custom_decoder(obj):
if isinstance(obj, dict) and '__type__' in obj:
if obj['__type__'] == 'CustomObject':
custom_obj = CustomObject(obj['name'], obj['value'])
custom_obj.created_at = datetime.datetime.fromisoformat(obj['created_at'])
return custom_obj
elif obj['__type__'] == 'datetime':
return datetime.datetime.fromisoformat(obj['value'])
elif obj['__type__'] == 'numpy_array':
return np.frombuffer(
obj['data'],
dtype=obj['dtype']
).reshape(obj['shape'])
return obj
# Complex data structure
complex_data = {
'users': [
CustomObject('John Doe', 100),
CustomObject('Jane Smith', 200)
],
'timestamp': datetime.datetime.now(),
'matrix': np.array([[1, 2, 3], [4, 5, 6]]),
'config': {
'debug': True,
'timeout': 30.5,
'features': ['auth', 'logging', 'metrics']
}
}
# Encode
packed_data = msgpack.packb(complex_data, default=custom_encoder)
print(f"Packed size: {len(packed_data)} bytes")
# Decode
unpacked_data = msgpack.unpackb(packed_data, object_hook=custom_decoder, raw=False)
print(f"Unpacked data: {unpacked_data}")
# Streaming processing
def stream_processing():
# Streaming encode
packer = msgpack.Packer(default=custom_encoder)
# Streaming processing of large data
stream_data = []
for i in range(10000):
item = {
'id': i,
'name': f'Item {i}',
'timestamp': datetime.datetime.now(),
'data': np.random.rand(10)
}
stream_data.append(packer.pack(item))
# Concatenate into one stream
combined_stream = b''.join(stream_data)
print(f"Stream size: {len(combined_stream)} bytes")
# Streaming decode
unpacker = msgpack.Unpacker(object_hook=custom_decoder, raw=False)
unpacker.feed(combined_stream)
decoded_items = []
for item in unpacker:
decoded_items.append(item)
print(f"Decoded {len(decoded_items)} items from stream")
return decoded_items
stream_processing()
# Performance measurement
import time
import json
def performance_benchmark():
# Generate test data
test_data = []
for i in range(10000):
test_data.append({
'id': i,
'name': f'User {i}',
'email': f'user{i}@example.com',
'active': i % 2 == 0,
'score': i * 1.5,
'tags': [f'tag{j}' for j in range(i % 5)]
})
# MessagePack encode
start_time = time.time()
msgpack_data = msgpack.packb(test_data)
msgpack_encode_time = time.time() - start_time
# MessagePack decode
start_time = time.time()
msgpack_decoded = msgpack.unpackb(msgpack_data, raw=False)
msgpack_decode_time = time.time() - start_time
# JSON encode
start_time = time.time()
json_data = json.dumps(test_data).encode()
json_encode_time = time.time() - start_time
# JSON decode
start_time = time.time()
json_decoded = json.loads(json_data.decode())
json_decode_time = time.time() - start_time
# Output results
print(f"MessagePack encode: {msgpack_encode_time:.4f}s")
print(f"MessagePack decode: {msgpack_decode_time:.4f}s")
print(f"MessagePack size: {len(msgpack_data)} bytes")
print(f"JSON encode: {json_encode_time:.4f}s")
print(f"JSON decode: {json_decode_time:.4f}s")
print(f"JSON size: {len(json_data)} bytes")
print(f"Encode speedup: {json_encode_time / msgpack_encode_time:.1f}x")
print(f"Decode speedup: {json_decode_time / msgpack_decode_time:.1f}x")
print(f"Size reduction: {(len(json_data) - len(msgpack_data)) / len(json_data) * 100:.1f}%")
performance_benchmark()
Java Usage
// Assuming Maven dependencies are added
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.msgpack.value.Variable;
import java.io.IOException;
import java.util.*;
public class MessagePackExample {
// Basic serialization
public static void basicSerialization() throws IOException {
// Prepare data
Map<String, Object> userData = new HashMap<>();
userData.put("id", 123);
userData.put("name", "John Doe");
userData.put("email", "[email protected]");
userData.put("active", true);
userData.put("balance", 1234.56);
userData.put("tags", Arrays.asList("admin", "user"));
Map<String, Object> metadata = new HashMap<>();
metadata.put("createdAt", System.currentTimeMillis());
metadata.put("version", "1.0");
userData.put("metadata", metadata);
// Encode
MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
packer.packValue(MessagePack.newDefaultPacker().packValue(userData).build());
byte[] packed = packer.toByteArray();
packer.close();
System.out.println("Packed size: " + packed.length + " bytes");
// Decode
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(packed);
Value value = unpacker.unpackValue();
unpacker.close();
System.out.println("Unpacked value: " + value);
}
// High-performance streaming processing
public static void streamingProcessing() throws IOException {
// Streaming write of large data
MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
// Start array
packer.packArrayHeader(10000);
for (int i = 0; i < 10000; i++) {
packer.packMapHeader(4);
packer.packString("id").packInt(i);
packer.packString("name").packString("User " + i);
packer.packString("timestamp").packLong(System.currentTimeMillis());
packer.packString("active").packBoolean(i % 2 == 0);
}
byte[] packed = packer.toByteArray();
packer.close();
System.out.println("Stream packed size: " + packed.length + " bytes");
// Streaming read
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(packed);
int arraySize = unpacker.unpackArrayHeader();
System.out.println("Processing " + arraySize + " items");
int processedCount = 0;
while (unpacker.hasNext() && processedCount < arraySize) {
int mapSize = unpacker.unpackMapHeader();
Map<String, Object> item = new HashMap<>();
for (int i = 0; i < mapSize; i++) {
String key = unpacker.unpackString();
Value value = unpacker.unpackValue();
item.put(key, value);
}
processedCount++;
// Show progress every 100 items
if (processedCount % 100 == 0) {
System.out.println("Processed: " + processedCount + " items");
}
}
unpacker.close();
System.out.println("Total processed: " + processedCount + " items");
}
// Binary data handling
public static void binaryDataHandling() throws IOException {
MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
// Create binary data
byte[] binaryData = new byte[1024];
for (int i = 0; i < binaryData.length; i++) {
binaryData[i] = (byte) (i % 256);
}
// Object containing binary data
packer.packMapHeader(3);
packer.packString("filename").packString("data.bin");
packer.packString("size").packInt(binaryData.length);
packer.packString("content").packBinaryHeader(binaryData.length);
packer.addPayload(binaryData);
byte[] packed = packer.toByteArray();
packer.close();
System.out.println("Binary data packed size: " + packed.length + " bytes");
// Read binary data
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(packed);
int mapSize = unpacker.unpackMapHeader();
String filename = null;
int size = 0;
byte[] content = null;
for (int i = 0; i < mapSize; i++) {
String key = unpacker.unpackString();
switch (key) {
case "filename":
filename = unpacker.unpackString();
break;
case "size":
size = unpacker.unpackInt();
break;
case "content":
int binarySize = unpacker.unpackBinaryHeader();
content = new byte[binarySize];
unpacker.readPayload(content);
break;
}
}
unpacker.close();
System.out.println("Filename: " + filename);
System.out.println("Size: " + size);
System.out.println("Content length: " + (content != null ? content.length : 0));
System.out.println("Binary data integrity: " +
(content != null && content.length == binaryData.length &&
Arrays.equals(content, binaryData) ? "OK" : "FAILED"));
}
public static void main(String[] args) {
try {
System.out.println("=== Basic Serialization ===");
basicSerialization();
System.out.println("\n=== Streaming Processing ===");
streamingProcessing();
System.out.println("\n=== Binary Data Handling ===");
binaryDataHandling();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Web Application Integration and Real-time Communication
// Real-time communication with WebSocket + MessagePack
import { encode, decode } from '@msgpack/msgpack';
class MessagePackWebSocket {
constructor(url) {
this.ws = new WebSocket(url);
this.ws.binaryType = 'arraybuffer';
this.messageHandlers = new Map();
this.ws.onmessage = (event) => {
try {
const data = decode(new Uint8Array(event.data));
this.handleMessage(data);
} catch (error) {
console.error('Failed to decode MessagePack data:', error);
}
};
}
send(type, payload) {
if (this.ws.readyState === WebSocket.OPEN) {
const message = {
type,
payload,
timestamp: Date.now()
};
const encoded = encode(message);
this.ws.send(encoded);
}
}
on(messageType, handler) {
this.messageHandlers.set(messageType, handler);
}
handleMessage(data) {
const handler = this.messageHandlers.get(data.type);
if (handler) {
handler(data.payload);
}
}
}
// High-speed game data synchronization
class GameStateSync {
constructor(websocket) {
this.ws = websocket;
this.gameState = {
players: new Map(),
entities: new Map(),
worldState: {}
};
// Handle player state updates
this.ws.on('player_update', (data) => {
this.updatePlayer(data);
});
// Handle entity state updates
this.ws.on('entity_update', (data) => {
this.updateEntity(data);
});
// Regular state synchronization (60FPS)
setInterval(() => {
this.syncState();
}, 1000 / 60);
}
updatePlayer(playerData) {
this.gameState.players.set(playerData.id, {
position: { x: playerData.x, y: playerData.y, z: playerData.z },
rotation: { x: playerData.rx, y: playerData.ry, z: playerData.rz },
health: playerData.health,
timestamp: playerData.timestamp
});
}
updateEntity(entityData) {
this.gameState.entities.set(entityData.id, {
type: entityData.type,
position: entityData.position,
state: entityData.state,
timestamp: entityData.timestamp
});
}
syncState() {
// Send only changed state (differential sync)
const changedPlayers = [];
const changedEntities = [];
// Detect player changes
this.gameState.players.forEach((player, id) => {
if (player.timestamp > Date.now() - 100) { // Changes within 100ms
changedPlayers.push({ id, ...player });
}
});
// Detect entity changes
this.gameState.entities.forEach((entity, id) => {
if (entity.timestamp > Date.now() - 100) {
changedEntities.push({ id, ...entity });
}
});
if (changedPlayers.length > 0 || changedEntities.length > 0) {
this.ws.send('state_sync', {
players: changedPlayers,
entities: changedEntities,
timestamp: Date.now()
});
}
}
}
// MessagePack support in REST API
class MessagePackAPI {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const headers = {
'Content-Type': 'application/msgpack',
'Accept': 'application/msgpack',
...options.headers
};
let body = options.body;
if (body && typeof body === 'object') {
body = encode(body);
}
const response = await fetch(url, {
...options,
headers,
body
});
if (response.headers.get('content-type')?.includes('application/msgpack')) {
const arrayBuffer = await response.arrayBuffer();
return decode(new Uint8Array(arrayBuffer));
} else {
return response.json();
}
}
async get(endpoint) {
return this.request(endpoint, { method: 'GET' });
}
async post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: data
});
}
}
// Usage examples
const wsClient = new MessagePackWebSocket('wss://game.example.com/ws');
const gameSync = new GameStateSync(wsClient);
const api = new MessagePackAPI('https://api.example.com');
// API usage example
async function loadUserData() {
try {
const userData = await api.get('/users/123');
console.log('User data:', userData);
const updateResult = await api.post('/users/123', {
name: 'John Doe',
email: '[email protected]',
preferences: {
theme: 'dark',
notifications: true
}
});
console.log('Update result:', updateResult);
} catch (error) {
console.error('API error:', error);
}
}
loadUserData();