Skip to content

abubalo/extended-json-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

49 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Extended JSON Parser

A modular, extensible JSON parser and serializer built from scratch in TypeScript for deep learning and exploration of data serialization concepts.

Overview

This project implements a complete JSON parser and serializer with support for extended data types beyond standard JSON.

Features

Core Functionality

  • Full JSON Compliance - Supports all standard JSON types (string, number, boolean, null, object, array)
  • Custom Parser - Hand-written tokenizer and recursive descent parser
  • Custom Serializer - Configurable stringification with formatting options
  • Error Handling - Detailed error messages with position tracking

Extended Type Support

  • πŸ“… Date Objects - Automatic ISO 8601 date parsing and serialization
  • πŸ—ΊοΈ Map Support - Serialize and deserialize ES6 Map objects with any key types
  • 🎯 Set Support - Full Set object support with nested structures
  • πŸ’¬ Comments - Single-line (//) and multi-line (/* */) comment support
  • πŸ”· Undefined - Optional undefined value serialization
  • πŸ”„ Circular Detection - Prevents infinite loops with circular reference detection

Advanced Features

  • Reviver Function - Transform values during parsing (like JSON.parse)
  • Replacer Function - Filter/transform values during serialization (like JSON.stringify)
  • Trailing Commas - Allowed when extensions are enabled
  • Custom Extensions - Plugin architecture for adding your own types

Installation

# Clone the repository
git clone https://github.com/abubalo/extended-json-parser.git
cd extended-json-parser

# Install dependencies
npm install

Quick Start

Basic Usage

import { _JSON } from './src/index';

// Simple parsing
const data = _JSON.parse('{"name": "Alice", "age": 30}');
console.log(data); // { name: 'Alice', age: 30 }

// Simple stringification
const json = _JSON.stringify({ name: "Bob", active: true });
console.log(json); // {"name":"Bob","active":true}

Pretty Printing

const obj = {
  person: {
    name: "Alice",
    age: 30,
    skills: ["JavaScript", "Python", "TypeScript"]
  }
};

const formatted = _JSON.stringify(obj, { space: 2 });
console.log(formatted);
// {
//   "person": {
//     "name": "Alice",
//     "age": 30,
//     "skills": [
//       "JavaScript",
//       "Python",
//       "TypeScript"
//     ]
//   }
// }

Date Support

const event = {
  name: "Meeting",
  date: new Date("2025-10-31T10:00:00.000Z")
};

// Serialize with date support
const json = _JSON.stringify(event, {
  extensions: { dates: true },
  space: 2
});

// Parse with automatic date conversion
const parsed = _JSON.parse(json, {
  extensions: { dates: true }
});

console.log(parsed.date instanceof Date); // true

Map and Set Support

// Map example
const userMap = new Map([
  ["alice", { role: "admin", active: true }],
  ["bob", { role: "user", active: false }]
]);

const json = _JSON.stringify(
  { users: userMap },
  { extensions: { maps: true }, space: 2 }
);

const parsed = _JSON.parse(json, { extensions: { maps: true } });
console.log(parsed.users instanceof Map); // true
console.log(parsed.users.get("alice")); // { role: 'admin', active: true }

// Set example
const tags = new Set(["javascript", "typescript", "nodejs"]);
const json2 = _JSON.stringify(
  { tags },
  { extensions: { sets: true } }
);

const parsed2 = _JSON.parse(json2, { extensions: { sets: true } });
console.log(parsed2.tags instanceof Set); // true

Comments in JSON

const jsonWithComments = `{
  // User configuration
  "name": "Alice",
  /* 
   * Multi-line comment
   * explaining the age field
   */
  "age": 30
}`;

const data = _JSON.parse(jsonWithComments, {
  extensions: { comments: true }
});

console.log(data); // { name: 'Alice', age: 30 }

Reviver and Replacer

// Reviver - transform during parsing
const json = '{"price": "100", "tax": "15"}';
const data = _JSON.parse(json, {
  reviver: (key, value) => {
    if (key === "price" || key === "tax") {
      return parseInt(value);
    }
    return value;
  }
});
console.log(data); // { price: 100, tax: 15 }

// Replacer - filter during serialization
const obj = { 
  name: "Alice", 
  password: "secret123", 
  age: 30 
};

const safe = _JSON.stringify(obj, {
  replacer: (key, value) => {
    if (key === "password") return undefined;
    return value;
  },
  space: 2
});
// Output won't include password field

Complex Nested Structures

const complex = {
  users: new Map([
    ["alice", new Set(["admin", "editor"])],
    ["bob", new Set(["viewer"])]
  ]),
  metadata: {
    created: new Date("2025-01-15T08:00:00.000Z"),
    updated: new Date("2025-10-31T12:00:00.000Z")
  }
};

const json = _JSON.stringify(complex, {
  extensions: { 
    maps: true, 
    sets: true, 
    dates: true 
  },
  space: 2
});

const parsed = _JSON.parse(json, {
  extensions: { 
    maps: true, 
    sets: true, 
    dates: true 
  }
});

// All types are preserved
console.log(parsed.users instanceof Map); // true
console.log(parsed.users.get("alice") instanceof Set); // true
console.log(parsed.metadata.created instanceof Date); // true

πŸ”§ API Reference

_JSON.parse(text, options?)

Parses a JSON string into a JavaScript value.

Parameters:

  • text (string) - The JSON string to parse
  • options (ParserOptions) - Optional configuration
    • reviver - Function to transform values during parsing
    • extensions - Enable extended features
      • dates (boolean) - Auto-parse ISO date strings
      • comments (boolean) - Allow comments in JSON
      • undefined (boolean) - Support undefined values
      • maps (boolean) - Deserialize Map objects
      • sets (boolean) - Deserialize Set objects

Returns: Parsed JavaScript value

Throws: JSONParseError if parsing fails

_JSON.stringify(value, options?)

Converts a JavaScript value to a JSON string.

Parameters:

  • value (JsonValue) - The value to serialize
  • options (StringifyOptions) - Optional configuration
    • replacer - Function to filter/transform values
    • space (string | number) - Indentation for pretty-printing
    • extensions - Enable extended features
      • dates (boolean) - Serialize Date objects
      • undefined (boolean) - Include undefined values
      • maps (boolean) - Serialize Map objects
      • sets (boolean) - Serialize Set objects

Returns: JSON string

Throws: TypeError for circular references or unsupported types

πŸ“š Learning Objectives

This project was built to understand:

Core Concepts

  • βœ… JSON specification and format structure
  • βœ… Lexical analysis and tokenization
  • βœ… Recursive descent parsing techniques
  • βœ… Abstract Syntax Tree (AST) concepts
  • βœ… Serialization and deserialization patterns

Advanced Topics

  • Error handling and recovery strategies
  • Circular reference detection
  • Extension architecture and plugins
  • Type preservation across serialization
  • Modular software design patterns

πŸ§ͺ Supported Data Types

Standard JSON Types

Type Parse Stringify Notes
String βœ… βœ… Full escape sequence support
Number βœ… βœ… IEEE 754 double precision
Boolean βœ… βœ… true / false
Null βœ… βœ… null
Object βœ… βœ… Nested objects supported
Array βœ… βœ… Mixed-type arrays supported

Extended Types (Optional)

Type Parse Stringify Extension Required
Date βœ… βœ… dates: true
Map βœ… βœ… maps: true
Set βœ… βœ… sets: true
Undefined βœ… βœ… undefined: true
Comments βœ… ❌ comments: true

🚧 Future Enhancements

Potential additions for continued learning:

  • BigInt Support - Handle arbitrarily large integers
  • Binary Data - Base64 encoded buffers/typed arrays
  • RegExp Serialization - Regular expression support
  • Symbol Support - Symbol.for() registry handling
  • Performance Benchmarks - Compare against native JSON
  • Streaming Parser - Handle large files without loading into memory
  • Source Maps - Map parsed values back to original positions
  • JSON Schema Validation - Built-in validation during parsing
  • Custom Formatting Rules - Configurable code style preferences

πŸ› Known Limitations

  • Performance is not optimized (educational focus)
  • No streaming support (loads entire input)
  • Extensions are format-breaking (not standard JSON)
  • Limited to UTF-8 string input
  • No async/await support for parsing

πŸ“– Resources & References

πŸ“„ License

MIT License - Feel free to use this for learning and education.

🀝 Contributing

This is primarily a learning project, but suggestions and improvements are welcome! Feel free to:

  • Open issues for bugs or questions
  • Submit PRs for enhancements
  • Share your own extensions
  • Use it for educational purposes

⭐ Acknowledgments

Built as a personal learning journey to deeply understand:

  • How parsers work at a fundamental level
  • The challenges of data serialization
  • Software architecture and modularity
  • TypeScript's type system capabilities

Happy Learning! πŸš€

If you found this helpful for understanding JSON parsing, please star the repo!

About

A custom implementation of JSON parser and serializer in Typescript

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published