json5 vs yaml vs toml vs hjson
Choosing the Right Configuration Format for Modern Frontend Projects
json5yamltomlhjsonSimilar Packages:

Choosing the Right Configuration Format for Modern Frontend Projects

hjson, json5, toml, and yaml are all alternatives to standard JSON, designed to make configuration files more human-readable and easier to maintain. While standard JSON is strict and machine-friendly, these formats relax syntax rules to support comments, trailing commas, and cleaner structures. json5 and hjson act as direct superset upgrades to JSON, toml focuses on explicit key-value pairs similar to INI files, and yaml uses indentation to create deeply nested, readable data structures. Choosing the right one depends on your team's need for comments, nesting depth, and existing tooling ecosystem.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
json5184,137,9487,166235 kB40-MIT
yaml149,540,0691,691686 kB3311 days agoISC
toml16,433,312326134 kB02 months agoMIT
hjson328,702432-286 years agoMIT

Hjson vs JSON5 vs TOML vs YAML: A Deep Dive into Configuration Formats

When building modern frontend applications, configuration files are everywhere. We use them for bundlers, linters, deployment scripts, and environment settings. While standard JSON is the default for data exchange, it falls short for human-written configs: it forbids comments, demands strict quoting, and hates trailing commas. This leads to merge conflicts and frustration.

Enter hjson, json5, toml, and yaml. These formats solve the "human readability" problem in different ways. Let's break down how they handle real-world engineering scenarios.

๐Ÿ’ฌ Comments: The Dealbreaker

The most common reason to switch from JSON is the ability to add comments. Documentation inside config files saves hours of debugging.

hjson allows both hash (#) and slash (//) comments naturally.

# Database settings for local dev
{
  host: localhost  # No quotes needed for simple strings
  port: 5432
  // You can also use C-style comments
}

json5 supports standard JavaScript-style comments (// and /* */).

{
  // API configuration
  "endpoint": "https://api.example.com",
  "timeout": 5000, /* milliseconds */
  "retry": true
}

toml uses the hash symbol (#) for comments, similar to Python or Ruby.

# Server configuration
host = "localhost"
port = 5432

# This is a timeout setting
timeout = 5000

yaml uses the hash symbol (#) for comments, placed at the start of the line or after content.

# Database settings
host: localhost
port: 5432
timeout: 5000  # milliseconds

๐Ÿ“ Syntax Strictness: Quotes and Commas

Developers often forget quotes around keys or leave a trailing comma at the end of a list. Standard JSON crashes on these mistakes. These alternatives handle them differently.

hjson is the most forgiving. It does not require quotes for keys or simple string values, and it ignores trailing commas.

{
  name: My App
  features: [
    login,
    dashboard,  # Trailing comma is fine
  ]
}

json5 allows unquoted keys if they are valid JavaScript identifiers and permits trailing commas. It still requires quotes for complex strings.

{
  name: 'My App',
  features: [
    'login',
    'dashboard',  # Trailing comma allowed
  ],
  'special-key': 'value' // Quotes required for special chars
}

toml requires quotes for strings but does not use commas to separate key-value pairs. Lists (arrays) do require commas.

name = "My App"
features = ["login", "dashboard"] # Commas needed here
# No commas between different keys

yaml relies on indentation and colons. No quotes are needed for simple strings, and no commas are used for lists.

name: My App
features:
  - login
  - dashboard
# No commas anywhere

๐ŸŒณ Nesting and Structure

How your data is organized matters. Some formats shine with flat settings; others handle deep trees better.

hjson handles nesting just like JSON, using curly braces. It remains readable even with depth due to optional quotes.

{
  database: {
    primary: {
      host: db1.example.com
      credentials: {
        user: admin
        pass: secret
      }
    }
  }
}

json5 also uses curly braces for nesting. It looks exactly like a JavaScript object.

{
  database: {
    primary: {
      host: "db1.example.com",
      credentials: {
        user: "admin",
        pass: "secret"
      }
    }
  }
}

toml uses "tables" (sections) denoted by brackets to handle nesting. This can feel cleaner for flat configs but gets verbose for deep trees.

[database.primary]
host = "db1.example.com"

[database.primary.credentials]
user = "admin"
pass = "secret"

yaml uses indentation to define nesting. This is very clean for deep structures but risky if you mix spaces and tabs.

database:
  primary:
    host: db1.example.com
    credentials:
      user: admin
      pass: secret

โš ๏ธ Maintenance Status and Risks

Before adopting a format, you must check if the library is still maintained. Using abandoned packages introduces security risks.

hjson: The original hjson package on npm is deprecated. The maintainers have archived the project. While the format itself is stable, you should not install the old hjson package for new projects. If you need this syntax, look for actively maintained forks or consider json5 instead.

json5: This package is actively maintained. It is widely used in the JavaScript ecosystem (e.g., by Babel) and receives regular updates. It is a safe choice for production.

toml: There are multiple TOML parsers on npm. The package simply named toml is older and sees infrequent updates. For modern projects, prefer actively maintained alternatives like @iarna/toml or toml-parse. Always verify the specific parser you choose is receiving security patches.

yaml: The yaml package (by eemeli) is the modern, recommended standard for JavaScript. It replaced the older js-yaml in many contexts due to better performance and spec compliance. It is actively maintained and robust.

๐Ÿ›  Real-World Use Cases

Scenario 1: Local Developer Config

You need a config file that developers edit daily. They keep breaking the build by forgetting commas.

  • โœ… Best Choice: hjson (if using a maintained fork) or json5.
  • Why? The loose syntax prevents simple syntax errors from stopping the workflow.
// .babelrc.json5
{
  presets: ['@babel/preset-env'],
  plugins: [
    'transform-runtime', // Forgot comma? No problem in JSON5/Hjson
  ]
}

Scenario 2: CI/CD Pipeline Definition

You are defining a complex workflow with steps, conditions, and nested jobs.

  • โœ… Best Choice: yaml.
  • Why? GitHub Actions, GitLab CI, and CircleCI all use YAML. Sticking to the standard ensures compatibility and tooling support.
# .github/workflows/deploy.yml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install

Scenario 3: Build Tool Configuration

You are configuring a Rust or Python toolchain integrated into your frontend build.

  • โœ… Best Choice: toml.
  • Why? Tools like Cargo (Rust) and Poetry (Python) use TOML. Keeping a consistent format across languages reduces context switching.
# pyproject.toml
[tool.poetry]
name = "my-app"
version = "0.1.0"

[tool.poetry.dependencies]
python = "^3.8"

๐Ÿ“Š Summary Comparison

Featurehjsonjson5tomlyaml
Commentsโœ… # and //โœ… // and /* */โœ… #โœ… #
Quotes on KeysโŒ Optionalโš ๏ธ Optional (JS rules)โŒ NeverโŒ Optional
Trailing Commasโœ… Allowedโœ… AllowedโŒ Not applicableโŒ Not applicable
Nesting StyleBraces {}Braces {}Sections []Indentation
Maintenanceโš ๏ธ Deprecated (npm)โœ… Activeโš ๏ธ Varies by libโœ… Active
Best ForHuman editingJS ecosystemsFlat configsDevOps/Complex

๐Ÿ’ก Final Recommendation

If you are starting a new JavaScript-heavy project and need better config files today, json5 is the pragmatic winner. It offers the best balance of features, active maintenance, and familiarity for JS developers. It solves the comment and comma problems without introducing a completely new syntax.

Choose yaml only if you are integrating with DevOps tools (Kubernetes, GitHub Actions) or need to represent very deep, complex data structures where indentation improves readability.

Choose toml if you are building a polyglot system (mixing Rust, Python, and JS) where explicit key-value pairs are preferred over nested objects.

Avoid the deprecated hjson npm package in new production systems. While the syntax is great, the lack of maintenance is a liability. Stick to json5 for similar benefits with better long-term support.

How to Choose: json5 vs yaml vs toml vs hjson

  • json5:

    Choose json5 if you want to upgrade your existing JSON files with minimal friction, adding support for comments and trailing commas while keeping the structure nearly identical to standard JSON. It is the safest bet for frontend projects (like Babel or Webpack configs) where you need better DX but still want the file to look familiar to JavaScript developers. Use this when you need broad library support and a syntax that feels like natural JavaScript object literals.

  • yaml:

    Choose yaml if you are working in an ecosystem that already relies on it (like Kubernetes, GitHub Actions, or Docker Compose) or if you need to represent complex, deeply nested data structures cleanly. It is the industry standard for DevOps and CI/CD configurations where readability and hierarchy matter more than strict syntax rules. Be aware that YAML's reliance on whitespace indentation can lead to subtle bugs, so it requires disciplined formatting and good linting tools.

  • toml:

    Choose toml if your configuration consists mostly of flat key-value pairs and simple tables, and you prioritize explicitness over deep nesting. It is an excellent choice for build tool configurations (like Rust's Cargo or Python's Poetry) where clarity and avoiding indentation errors are top priorities. Avoid toml if your data structure requires complex, deeply nested objects, as the syntax can become verbose and harder to read compared to YAML.

  • hjson:

    Choose hjson if you need a configuration format that is extremely forgiving and readable for humans, specifically allowing unquoted keys and trailing commas without strict syntax errors. It is ideal for local development config files where developers frequently edit values manually and might forget quotes or add extra commas. However, avoid it for critical production pipelines where strict standardization across different languages is required, as its ecosystem is smaller than JSON5 or YAML.

README for json5

JSON5 โ€“ JSON for Humans

Build Status Coverage
Status

JSON5 is an extension to the popular JSON file format that aims to be easier to write and maintain by hand (e.g. for config files). It is not intended to be used for machine-to-machine communication. (Keep using JSON or other file formats for that. ๐Ÿ™‚)

JSON5 was started in 2012, and as of 2022, now gets >65M downloads/week, ranks in the top 0.1% of the most depended-upon packages on npm, and has been adopted by major projects like Chromium, Next.js, Babel, Retool, WebStorm, and more. It's also natively supported on Apple platforms like MacOS and iOS.

Formally, the JSON5 Data Interchange Format is a superset of JSON (so valid JSON files will always be valid JSON5 files) that expands its syntax to include some productions from ECMAScript 5.1 (ES5). It's also a strict subset of ES5, so valid JSON5 files will always be valid ES5.

This JavaScript library is a reference implementation for JSON5 parsing and serialization, and is directly used in many of the popular projects mentioned above (where e.g. extreme performance isn't necessary), but others have created many other libraries across many other platforms.

Summary of Features

The following ECMAScript 5.1 features, which are not supported in JSON, have been extended to JSON5.

Objects

  • Object keys may be an ECMAScript 5.1 IdentifierName.
  • Objects may have a single trailing comma.

Arrays

  • Arrays may have a single trailing comma.

Strings

  • Strings may be single quoted.
  • Strings may span multiple lines by escaping new line characters.
  • Strings may include character escapes.

Numbers

  • Numbers may be hexadecimal.
  • Numbers may have a leading or trailing decimal point.
  • Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
  • Numbers may begin with an explicit plus sign.

Comments

  • Single and multi-line comments are allowed.

White Space

  • Additional white space characters are allowed.

Example

Kitchen-sink example:

{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}

A more real-world example is this config file from the Chromium/Blink project.

Specification

For a detailed explanation of the JSON5 format, please read the official specification.

Installation and Usage

Node.js

npm install json5

CommonJS

const JSON5 = require('json5')

Modules

import JSON5 from 'json5'

Browsers

UMD

<!-- This will create a global `JSON5` variable. -->
<script src="https://unpkg.com/json5@2/dist/index.min.js"></script>

Modules

<script type="module">
  import JSON5 from 'https://unpkg.com/json5@2/dist/index.min.mjs'
</script>

API

The JSON5 API is compatible with the JSON API.

JSON5.parse()

Parses a JSON5 string, constructing the JavaScript value or object described by the string. An optional reviver function can be provided to perform a transformation on the resulting object before it is returned.

Syntax

JSON5.parse(text[, reviver])

Parameters

  • text: The string to parse as JSON5.
  • reviver: If a function, this prescribes how the value originally produced by parsing is transformed, before being returned.

Return value

The object corresponding to the given JSON5 text.

JSON5.stringify()

Converts a JavaScript value to a JSON5 string, optionally replacing values if a replacer function is specified, or optionally including only the specified properties if a replacer array is specified.

Syntax

JSON5.stringify(value[, replacer[, space]])
JSON5.stringify(value[, options])

Parameters

  • value: The value to convert to a JSON5 string.
  • replacer: A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON5 string. If this value is null or not provided, all properties of the object are included in the resulting JSON5 string.
  • space: A String or Number object that's used to insert white space into the output JSON5 string for readability purposes. If this is a Number, it indicates the number of space characters to use as white space; this number is capped at 10 (if it is greater, the value is just 10). Values less than 1 indicate that no space should be used. If this is a String, the string (or the first 10 characters of the string, if it's longer than that) is used as white space. If this parameter is not provided (or is null), no white space is used. If white space is used, trailing commas will be used in objects and arrays.
  • options: An object with the following properties:
    • replacer: Same as the replacer parameter.
    • space: Same as the space parameter.
    • quote: A String representing the quote character to use when serializing strings.

Return value

A JSON5 string representing the value.

Node.js require() JSON5 files

When using Node.js, you can require() JSON5 files by adding the following statement.

require('json5/lib/register')

Then you can load a JSON5 file with a Node.js require() statement. For example:

const config = require('./config.json5')

CLI

Since JSON is more widely used than JSON5, this package includes a CLI for converting JSON5 to JSON and for validating the syntax of JSON5 documents.

Installation

npm install --global json5

Usage

json5 [options] <file>

If <file> is not provided, then STDIN is used.

Options:

  • -s, --space: The number of spaces to indent or t for tabs
  • -o, --out-file [file]: Output to the specified file, otherwise STDOUT
  • -v, --validate: Validate JSON5 but do not output JSON
  • -V, --version: Output the version number
  • -h, --help: Output usage information

Contributing

Development

git clone https://github.com/json5/json5
cd json5
npm install

When contributing code, please write relevant tests and run npm test and npm run lint before submitting pull requests. Please use an editor that supports EditorConfig.

Issues

To report bugs or request features regarding the JSON5 data format, please submit an issue to the official specification repository.

Note that we will never add any features that make JSON5 incompatible with ES5; that compatibility is a fundamental premise of JSON5.

To report bugs or request features regarding this JavaScript implementation of JSON5, please submit an issue to this repository.

Security Vulnerabilities and Disclosures

To report a security vulnerability, please follow the follow the guidelines described in our security policy.

License

MIT. See LICENSE.md for details.

Credits

Aseem Kishore founded this project. He wrote a blog post about the journey and lessons learned 10 years in.

Michael Bolin independently arrived at and published some of these same ideas with awesome explanations and detail. Recommended reading: Suggested Improvements to JSON

Douglas Crockford of course designed and built JSON, but his state machine diagrams on the JSON website, as cheesy as it may sound, gave us motivation and confidence that building a new parser to implement these ideas was within reach! The original implementation of JSON5 was also modeled directly off of Dougโ€™s open-source json_parse.js parser. Weโ€™re grateful for that clean and well-documented code.

Max Nanasy has been an early and prolific supporter, contributing multiple patches and ideas.

Andrew Eisenberg contributed the original stringify method.

Jordan Tucker has aligned JSON5 more closely with ES5, wrote the official JSON5 specification, completely rewrote the codebase from the ground up, and is actively maintaining this project.