npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

json-storage-formatter

v3.0.2

Published

Package for json stringify objects without losing data types

Downloads

1,588

Readme

json-storage-formatter 🌟

Image John Avatar

A lightweight solution to format complex JavaScript objects for string-based storage systems without losing their types. 🚀

🤔 The Problem?

const userProfile = {
  id: 42,
  createdAt: new Date('2024-10-01T10:30:00Z'),
  preferences: new Map([
    ['theme', 'dark'],
    ['languages', new Set(['en', 'es'])],
  ]),
};

console.log(JSON.stringify(userProfile, null, 2));

Console Output:

{
  "id": 42,
  "createdAt": "2024-10-01T10:30:00.000Z",
  "preferences": {}
}

When working with tools like localStorage, sessionStorage, AsyncStorage, or even databases like Redis or PostgreSQL (JSON columns), we often need to store application state or configuration objects as strings using JSON.stringify.

But there’s a catch!:

JSON.stringify has no idea what to do with values like Date, Map, or Set...
It just flattens them into empty objects or strings, making you lose the original data types or the entire structure.


💡 What json-storage-formatter Does

Exposes two simple functions:

  1. formatToStore(value) → safely prepares your data for storage, returning a JSON string representation.
  2. formatFromStore(value) → restores it to the exact original shape and types.

As simple as that.

Let’s see a couple of examples


⚙️ Example: useDashboardConfig Hook

Let’s create a hook that syncs localStorage with React state:

import { formatToStore, formatFromStore } from 'json-storage-formatter';

type DashboardConfig = {
  theme: 'light' | 'dark' | 'system';
  widgets: Map<string, WidgetConfig>;
  hiddenWidgets: Set<string>;
  lastCustomizedAt: Date;
};

const useDashboardConfig = () => {
  const [config, setConfig] = useState<DashboardConfig>(() => {
    const json = localStorage.getItem('dashboard-config');

    if (json) return formatFromStore<DashboardConfig>(json);

    return getDefaultDashboardConfig();
  });

  const saveConfig = (newConfig: DashboardConfig) => {
    localStorage.setItem('dashboard-config', formatToStore(newConfig));
    setConfig(newConfig);
  };

  return { config, saveConfig };
};

// Even if the config contains Maps, Sets, or Dates, they will be preserved.
const example: DashboardConfig = {
  theme: 'dark',
  widgets: new Map([
    ['weather', { location: 'New York', units: 'metric' }],
    ['stocks', { symbols: ['AAPL', 'GOOGL'] }],
  ]),
  hiddenWidgets: new Set(['news']),
  lastCustomizedAt: new Date(),
};

🌐 Example: Sync Dashboard Queries Through URL (Dashboards / Reports)

This pattern is common in dashboards, where filters are shared via URL.
You can safely serialize complex filters (with Dates, Sets, Maps, etc.) and encode them for sharing.

import { formatToStore, formatFromStore } from 'json-storage-formatter';

type DashboardQuery = {
  dateRange: { from: Date; to: Date };
  selectedCategories: Set<string>;
  additionalSettings: Map<string, unknown>;
};

const useUrlQuery = () => {
  const [query, setQuery] = useState<DashboardQuery>(() => {
    const params = new URLSearchParams(location.search);
    const storedQuery = params.get('query');

    if (storedQuery) {
      // decode from base64 and restore types
      return formatFromStore<DashboardQuery>(atob(storedQuery));
    }

    return getDefaultDashboardQuery();
  });

  const updateQuery = (newQuery: DashboardQuery) => {
    const encoded = btoa(formatToStore(newQuery));

    // encode the JSON as base64 to make it URL-safe
    // avoids breaking query strings with +, /, or = characters
    window.history.replaceState(null, '', `\${location.pathname}?query=\${encoded}`);

    setQuery(newQuery);
  };

  return { query, updateQuery };
};

The examples above use React, but the library itself is framework-agnostic
and can be used anywhere in JavaScript or TypeScript projects.


🧩 Why It’s Useful

This becomes incredibly powerful when your app needs to sync complex state to a string-based storage layer — like when syncing to localStorage, Redis, or a shared dashboard URL.

Instead of being limited by what JSON can handle, you can now serialize any structure — Maps, Sets, nested objects, or Dates — and restore it back without losing context or meaning.


🧠 How It Works

Under the hood, formatToStore adds small metadata markers to every special value.
Each piece of data gets a structure like this:

{
  "$t": "map",
  "$v": [["key", { "$t": "date", "$v": "2024-10-01T10:30:00.000Z" }]]
}

The $t field stores the type, and $v holds the actual value.
When using formatFromStore, it reads that metadata and recreates your data structure
exactly as it was before — even if it’s deeply nested.

Resulting in:

new Map([['key', new Date('2024-10-01T10:30:00.000Z')]]);

⚙️ API Reference

🟣 formatToStore

Converts any value into a JSON-safe structure with internal type metadata.

const objectWithMetadata = formatToStore(object);

🔵 formatFromStore

Restores the serialized object back to its original types.

const result = formatFromStore<Map<string, unknown>>(objectWithMetadata);

Both functions work directly with strings,
so you can safely use them with localStorage, AsyncStorage, or URLs.


🧰 Utility Functions

| Function | Description | Example | | ------------- | ---------------------------------------- | ----------------------------- | | isNil | Checks if value is null or undefined | isNil(null); // true | | isNumber | Checks if value is a number | isNumber(42); // true | | isBoolean | Checks if value is a boolean | isBoolean(false); // true | | isString | Checks if value is a string | isString('hi'); // true | | isDate | Checks if value is a Date | isDate(new Date()); // true |


⚖️ Comparison

| Behavior | JSON.stringify | json-storage-formatter | | ------------- | --------------- | ------------------------ | | Date | Becomes string | ✅ Restored as Date | | Set | Lost completely | ✅ Restored as Set | | Map | Lost completely | ✅ Restored as Map | | Undefined | Omitted | ✅ Restored as undefined | | Regexp | Lost completely | ✅ Restored as RegExp | | Error | Lost completely | ✅ Restored as Error |


📦 Installation

npm install json-storage-formatter

or

yarn add json-storage-formatter

🎯 Ready to Try It?

📘 NPM: json-storage-formatter
Serialize, store, and restore any JavaScript data type without losing its identity — lightweight, fast. ✨