Introducing handlejson - Safe JSON Parsing Without the try-catch Spam

Published: (January 6, 2026 at 01:46 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Why a wrapper for JSON.parse?

I got tired of writing the same try‑catch boilerplate everywhere:

let data;
try {
  data = JSON.parse(str);
} catch {
  data = null;
}

Whether it was reading from localStorage, handling API responses, or parsing user input, the pattern repeated thousands of times.
Beyond the verbosity, native JSON has other quirks:

  • JSON.stringify throws on circular references.
  • Date objects become empty objects when stringified.
  • No built‑in way to validate the resulting structure.

Introducing handlejson

handlejson is a tiny wrapper around the native JSON functions that smooths out these edge cases.

import { parse, stringify } from 'handlejson';

// Safe parsing – returns null on error, no try‑catch needed
const user = parse(localStorage.getItem('user'));
const config = parse(invalidJson, { default: {} });

// Handles circular references automatically
const obj = { a: 1 };
obj.self = obj;
stringify(obj); // '{"a":1,"self":"[Circular]"}'

// BigInt support
stringify({ value: BigInt(123) }); // '{"value":"123n"}'

The library is ~2.8 KB gzipped, has zero dependencies, and ships with full TypeScript typings. It works both in the browser and in Node.js.

New features in v0.2.0

Automatic date handling

Previously you needed a custom reviver to turn ISO strings back into Date objects:

// The old way
const user = parse(jsonString, {
  reviver: (key, value) => {
    if (key.endsWith('At') && typeof value === 'string') {
      const date = new Date(value);
      return isNaN(date.getTime()) ? value : date;
    }
    return value;
  }
});

Now it’s a single option:

const user = parse(jsonString, { dates: true });
// Dates are automatically converted

Stringifying also respects this option:

stringify({ createdAt: new Date() }, { dates: true });
// → '{"createdAt":"2023-01-01T10:00:00.000Z"}'

Simple schema validation

When API responses have the wrong types, you can validate the parsed object against a lightweight schema:

const schema = {
  name: 'string',
  age: 'number',
  active: 'boolean',
  address: {
    street: 'string',
    zip: 'number'
  }
};

const user = parse(apiResponse, { schema });
// Returns null if validation fails

The validation runs after parsing, producing clear error messages such as:

Field 'age': expected number, got string

Streaming large JSON files

For multi‑megabyte payloads you can parse incrementally:

import { parseStream } from 'handlejson';

const result = await parseStream(response.body, {
  onProgress: parsed => console.log('Loading...', parsed),
  onError: err => console.error('Error:', err)
});

if (result.complete) {
  console.log('Data:', result.data);
}

This avoids loading the entire file into memory at once.

Before vs. after

Before

function loadUser() {
  const stored = localStorage.getItem('user');
  if (!stored) return null;

  try {
    const parsed = JSON.parse(stored);
    if (parsed.createdAt) {
      parsed.createdAt = new Date(parsed.createdAt);
    }
    return parsed;
  } catch {
    return null;
  }
}

After

function loadUser() {
  return parse(localStorage.getItem('user'), {
    default: null,
    dates: true
  });
}

The new API is far cleaner, and you can add schema validation if desired.

How does it compare?

Other libraries exist, but many are heavier or include features you may never need. handlejson focuses on the most common pain points:

  • Small bundle size (~2.8 KB gzipped)
  • Zero runtime dependencies
  • Consistent API across browser and Node.js
  • Optional, opt‑in features that won’t break existing code

Installation

npm install handlejson

The v0.2.0 release is live on npm: .

All new functionality is optional, so upgrading won’t affect code that already uses the earlier version.

Closing thoughts

If you find yourself writing try‑catch blocks for JSON.parse all the time, handlejson can tidy up your code and catch common bugs early. If native JSON works fine for you, there’s no need to add a dependency.

What’s your experience with JSON parsing boilerplate? Feel free to share your thoughts!

Back to Blog

Related posts

Read more »