BSON

SerializationJavaScriptTypeScriptMongoDBBinary FormatNoSQL

Library

BSON

Overview

BSON (Binary JSON) is a binary-encoded format of JSON, developed as the primary data storage and transfer format for MongoDB. While maintaining the convenience of JSON, it provides fast parsing and traversal through binary format, and supports extended data types (dates, binary data, ObjectId, etc.). In JavaScript/TypeScript environments, it is integrated with MongoDB drivers and used transparently in database operations.

Details

BSON was designed to extend JSON's expressiveness while achieving efficient data storage and processing. By including length information for each element, it allows access to specific elements without parsing the entire data. MongoDB internally stores all documents in BSON format, optimizing index creation and query processing. It natively supports types that cannot be represented in standard JSON, such as dates, regular expressions, and binary data, supporting practical application development.

Key Features

  • Extended data types: Supports over 12 types including ObjectId, Date, Binary, Decimal128
  • Efficient traversal: Fast data access through length prefixes
  • MongoDB integration: Full support as MongoDB's standard data format
  • Language neutrality: Official drivers for multiple languages
  • Schema-less: Flexible data structure similar to JSON
  • Binary safe: Direct storage of binary data possible

Advantages and Disadvantages

Advantages

  • Native support for extended types like dates and binary data
  • Faster parsing and serialization than JSON
  • Seamless integration with MongoDB
  • Distributed system support with unique ObjectId generation
  • Efficient querying of nested structures
  • Preserves type information during storage and retrieval

Disadvantages

  • Tends to be larger in file size than JSON
  • Binary format not human-readable
  • Limited adoption outside MongoDB
  • Difficult to edit and debug in text editors
  • Higher learning curve than JSON
  • Limited support in some programming languages

References

Code Examples

Basic Usage

// Import BSON library
import { BSON, ObjectId } from 'bson';

// Create BSON document
const document = {
  _id: new ObjectId(),
  name: 'John Doe',
  age: 30,
  createdAt: new Date(),
  isActive: true,
  scores: [85, 90, 78],
  profile: {
    bio: 'Software Engineer',
    avatar: Buffer.from('binary data')
  }
};

// Serialize to BSON
const bsonData = BSON.serialize(document);
console.log('BSON size:', bsonData.length, 'bytes');

// Deserialize from BSON
const parsedDoc = BSON.deserialize(bsonData);
console.log('Parsed:', parsedDoc);

Using Extended JSON (EJSON)

import { EJSON } from 'bson';

// Document with extended types
const doc = {
  _id: new ObjectId(),
  price: BSON.Decimal128.fromString('99.99'),
  pattern: /^test$/i,
  binary: new BSON.Binary(Buffer.from('hello')),
  timestamp: new Date()
};

// Convert to EJSON (express extended types in string format)
const ejsonString = EJSON.stringify(doc, { relaxed: false });
console.log('EJSON:', ejsonString);

// Restore from EJSON
const restored = EJSON.parse(ejsonString);
console.log('Restored types:', {
  isObjectId: restored._id instanceof ObjectId,
  isDecimal: restored.price instanceof BSON.Decimal128,
  isRegExp: restored.pattern instanceof RegExp
});

MongoDB Integration

import { MongoClient, ObjectId } from 'mongodb';

async function mongoExample() {
  const client = new MongoClient('mongodb://localhost:27017');
  await client.connect();
  
  const db = client.db('myapp');
  const users = db.collection('users');
  
  // Insert document using BSON types
  const result = await users.insertOne({
    _id: new ObjectId(),
    name: 'Jane Smith',
    birthDate: new Date('1990-05-15'),
    tags: ['developer', 'tokyo'],
    metadata: new BSON.Binary(Buffer.from('metadata')),
    lastLogin: new Date()
  });
  
  // Query using ObjectId
  const user = await users.findOne({ 
    _id: new ObjectId(result.insertedId) 
  });
  
  // Range query using date type
  const recentUsers = await users.find({
    lastLogin: { $gte: new Date(Date.now() - 24*60*60*1000) }
  }).toArray();
  
  await client.close();
}

Custom Type Handling

import { BSON } from 'bson';

// Custom class
class Location {
  constructor(lat, lng) {
    this.latitude = lat;
    this.longitude = lng;
  }
  
  toBSON() {
    return {
      type: 'Point',
      coordinates: [this.longitude, this.latitude]
    };
  }
  
  static fromBSON(doc) {
    if (doc.type === 'Point') {
      return new Location(doc.coordinates[1], doc.coordinates[0]);
    }
    return doc;
  }
}

// Usage
const location = new Location(35.6762, 139.6503); // Tokyo
const bson = BSON.serialize({ location });
const parsed = BSON.deserialize(bson);
console.log('Location:', parsed.location);

Type-safe Usage with TypeScript

import { ObjectId, Decimal128 } from 'bson';

// Type definition
interface Product {
  _id: ObjectId;
  name: string;
  price: Decimal128;
  categories: string[];
  inStock: boolean;
  createdAt: Date;
  image?: Buffer;
}

// Type-safe BSON operations
function createProduct(data: Omit<Product, '_id'>): Product {
  return {
    _id: new ObjectId(),
    ...data
  };
}

const product = createProduct({
  name: 'TypeScript Guide',
  price: Decimal128.fromString('29.99'),
  categories: ['Books', 'Programming'],
  inStock: true,
  createdAt: new Date()
});

// Serialize/Deserialize
const bsonData = BSON.serialize(product);
const restored = BSON.deserialize(bsonData) as Product;

// Type checking is effective
console.log(restored.price.toString()); // "29.99"

Binary Data Processing

import { BSON } from 'bson';
import fs from 'fs';

// Save image file
async function saveImageToBSON(imagePath, outputPath) {
  const imageBuffer = await fs.promises.readFile(imagePath);
  
  const document = {
    filename: imagePath.split('/').pop(),
    contentType: 'image/jpeg',
    data: new BSON.Binary(imageBuffer),
    uploadedAt: new Date(),
    size: imageBuffer.length
  };
  
  const bsonData = BSON.serialize(document);
  await fs.promises.writeFile(outputPath, bsonData);
  
  return bsonData.length;
}

// Restore image
async function loadImageFromBSON(bsonPath) {
  const bsonData = await fs.promises.readFile(bsonPath);
  const document = BSON.deserialize(bsonData);
  
  // Get binary data as Buffer
  const imageBuffer = document.data.buffer;
  
  return {
    filename: document.filename,
    contentType: document.contentType,
    data: imageBuffer,
    size: document.size
  };
}