Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool

Automated JSON Formatting in Git Hooks

Maintaining consistent code style across a project is crucial for readability, collaboration, and reducing merge conflicts. While code formatters are common for languages like JavaScript, Python, or CSS, configuration files and data formats like JSON often get overlooked. Inconsistent JSON formatting can lead to noisy Git diffs and debates during code reviews. This article explores how to use Git hooks, specifically the pre-commit hook, to automatically format your JSON files before they are committed.

What are Git Hooks?

Git hooks are scripts that Git executes automatically at certain points in your workflow. They allow you to customize Git's internal behavior and trigger customizable actions. Hooks are typically stored in the .git/hooks directory of your repository. Examples include:

  • pre-commit: Runs before a commit is finalized. This is where you might check code style or run tests.
  • prepare-commit-msg: Runs before the commit message editor is launched.
  • post-commit: Runs after a commit is successfully created. Useful for notifications or triggers.
  • pre-rebase: Runs before a rebase starts.
  • And many more...

For automated formatting, the pre-commit hook is the ideal place. It ensures that any files you add to the staging area meet your formatting standards *before* they become part of the commit history. If the hook script exits with a non-zero status, the commit is aborted, giving you a chance to fix issues.

Setting up a Basic Manual Hook

You can set up a Git hook manually by navigating to the .git/hooks directory in your repository. You'll find example scripts with a .sample extension. To create your own hook, copy one of these or create a new file with the desired hook name (e.g., pre-commit) and make it executable.

Here's a basic example of a .git/hooks/pre-commit script using bash that finds staged JSON files and formats them. This requires a JSON formatting tool to be installed (we'll discuss tools next).

.git/hooks/pre-commit (Bash Example)

#!/bin/sh # Get list of staged files STAGED_FILES=$(git diff --cached --name-only --diff-filter=d) # Filter for JSON files JSON_FILES=$(echo "$STAGED_FILES" | grep '\.json') # If no JSON files are staged, exit successfully if [ -z "$JSON_FILES" ]; then echo "No JSON files staged. Skipping formatting." exit 0 fi echo "Formatting staged JSON files..." # Loop through JSON files and format them using a tool (e.g., jq) # Replace 'jq -S '.' "$file" > "$file.tmp" && mv "$file.tmp" "$file"' with your chosen formatting command for file in $JSON_FILES do if [ -f "$file" ]; then # Ensure file still exists # Use 'jq -S '.' "$file" > "$file.tmp" && mv "$file.tmp" "$file"' # or 'prettier --write "$file"' or similar echo "Formatting $file..." # Example using jq for pretty printing with sorted keys jq -S '.' "$file" > "$file.tmp" && mv "$file.tmp" "$file" if [ $? -ne 0 ]; then echo "Error formatting $file. Aborting commit." exit 1 fi # Add the formatted file back to the staging area git add "$file" fi done echo "JSON formatting complete." exit 0

Important: Make the script executable using chmod +x .git/hooks/pre-commit.

This manual approach works but has a few drawbacks:

  • Hooks are local to your machine and not cloned with the repository by default.
  • Managing multiple hooks and ensuring consistency across developers is hard.
  • Requires manually installing formatting tools on each developer's machine.

Choosing a JSON Formatting Tool

You'll need a command-line tool that can read a JSON file and output a consistently formatted version. Some popular options include:

  • jq: A lightweight and flexible command-line JSON processor. It's excellent for querying, transforming, and also formatting JSON.

    Example using jq:

    echo '{"b": 2, "a": 1}' | jq '.'
    { "b": 2, "a": 1 }

    jq '.' pretty-prints. jq -S '.' also sorts keys.

  • prettier: A widely-used opinionated code formatter that supports many languages, including JSON. If you're already using Prettier, adding JSON support is straightforward.

    Example using prettier:

    prettier --write path/to/your.json

    The --write flag formats the file in place.

  • Built-in Language Tools: Many languages have built-in JSON libraries that can be used for formatting from the command line. E.g., Python's json.tool, Node.js's JSON.stringify.

    Example using Python:

    cat path/to/your.json | python -m json.tool

Choose the tool that best fits your project's existing toolchain and your specific formatting needs (e.g., sorting keys, indentation style).

Using a Pre-commit Framework (Recommended)

To overcome the limitations of manual hooks, consider using a pre-commit framework. These tools manage hooks for you, making them easy to install, update, and share across a team. Popular options include:

  • pre-commit (Python package): A powerful and widely adopted framework configured via a .pre-commit-config.yaml file. It automatically installs tools (like jq or prettier) in isolated environments.
  • husky (Node.js package): If your project is Node.js-based, Husky allows you to easily configure Git hooks in your package.json.

Using pre-commit (the Python package) as an example:

  1. Install the framework (e.g., pip install pre-commit).
  2. Create a .pre-commit-config.yaml file in your repository root.
  3. Configure the hook for JSON formatting.
  4. Run pre-commit install in your repo to set up the Git hook.

A .pre-commit-config.yaml entry using prettier might look like this:

.pre-commit-config.yaml (Example)

repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 # Use the latest version hooks: - id: end-of-file-fixer # Example: ensures files end with a newline - id: trailing-whitespace # Example: removes trailing whitespace - repo: https://github.com/prettier/prettier # Prettier hook rev: 3.2.5 # Use the latest version hooks: - id: prettier files: \.json$ # Target only .json files # Add any additional Prettier arguments here, e.g. --print-width=100

This configuration tells pre-commit to use the official Prettier hook and apply it only to files ending in .json. Frameworks like this handle installing Prettier (or other tools) in an isolated environment, ensuring all developers use the same version and configuration.

Cautions and Best Practices

  • Performance: For very large JSON files, running a formatter on every commit might become slow. Consider if the formatting is strictly necessary for extremely large, machine-generated files.
  • Format Staged Files Only: Ensure your hook only formats files that have been explicitly added to the staging area (`git add`). This prevents unexpected modifications to files you weren't intending to commit. Most frameworks handle this correctly, and the manual script example above filters staged files.
  • Provide Feedback: Your hook script should output messages indicating which files are being formatted or if errors occur, so the developer understands what's happening during the commit.
  • Error Handling: If the formatting tool fails (e.g., due to invalid JSON syntax), the hook should exit with a non-zero status to abort the commit and alert the user.
  • Configuration: Use a shared configuration file for your formatter (e.g., .prettierrc) to ensure consistency when using tools like Prettier. Frameworks help enforce this configuration.

Conclusion

Automating JSON formatting with Git pre-commit hooks is an effective way to enforce consistency and improve the maintainability of your codebase. While a basic manual script provides a starting point, using a dedicated pre-commit framework is highly recommended for ease of installation, shared configuration, and managing multiple hooks. By integrating JSON formatting into your Git workflow, you ensure cleaner commits and reduce friction during development and code reviews.

Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool