I stopped maintaining 30 JSON files by hand with this one tool

If you've ever wondered how to reuse configuration values or how to easily inject them into your code, then I have the perfect tool for you.It's not just a JSON replacement but something more powerful that works with several config formats.Jsonnet is a JSON superset (extension) that evaluates dynamic data.

It's a configuration language that links many JSON files together through shared values.You specify values and functions in common Jsonnet files, then use them to generate your JSON, TOML, and YAML configuration files.A quick demo It's basically JSON on steroids Jsonnet looks nearly identical to JSON, without the mandatory quotations around keys.

To quickly see what I mean, you can install Jsonnet using your distro's package manager and execute: jsonnet --exec '{ hello: "world" }' Using "exec" causes Jsonnet to interpret the file path as code instead.Let's look at a more complicated example.Using the command jsonnet example.jsonnet, the following Jsonnet code...

local replicas = 3; { name: "web-server", enabled: true, replicas: replicas, cpuLimit: 0.5, maintainer: null, ports: [80, 443, 8080], resources: { requests: { memory: "256Mi" }, limits: { memory: "512Mi" }, }, } Produces the following JSON: { "cpuLimit": 0.5, "enabled": true, "maintainer": null, "name": "web-server", "ports": [80, 443, 8080], "replicas": 3, "resources": { "limits": { "memory": "512Mi" }, "requests": { "memory": "256Mi" } } } You can see the use of the variable "replicas" too, but that's not the only dynamic feature it offers.Jsonnet supports functions, inheritance, conditionals, imports, and even Python-like list comprehensions.Inheritance is one of the more useful features—although some don't like it in configuration languages, I think it's necessary.

local base = { foo: "foo", bar: { x: "x", baz: "baz", }, }; { child: base + { foo: "inherited", bar+: { baz: "inherited", }, }, } The "base + ..." inherits (and merges) values from "base." The "bar+" tells Jsonnet to merge that nested object too; without it, the child "bar" clobbers (overwrites) the parent.Here's a simple example of a function.Functions can return any valid data type, including other objects: local foo(bar) = bar * 2; { result: foo(21), } And conditionals: local enabled = true; { status: if enabled then "on" else "off", } What you'd use Jsonnet for Connecting all your configuration files and code Jsonnet is ideal in the following scenarios: Automating processes (e.g., build processes) using configuration files or boilerplate-heavy scripts Replicating types/code in multiple places As mentioned, Jsonnet supports JSON, TOML, INI, and YAML.

Many modern tools use such file formats and also typically require domain-specific knowledge (such as service names, URLs, etc.).Examples include Docker, Kubernetes, build orchestration tools (like Nx), task runners, and much more.Having a central registry to tie in project-specific configuration values is a massive help.

Runtime code often relies on environment variables, and since Jsonnet can produce raw strings, you can generate just about any file imaginable and plug in the necessary values.Sometimes I output .env files, other times raw constants/types in dedicated Python or Go files.Jsonnet has an extensive string manipulation library.

While not perfect, I've rarely encountered an issue I could not resolve.Why I love Jsonnet It's simple, widely adopted, well-supported, and solves a real problem Glue code was something I had been trying to tackle for a while.I often create a monorepository for large projects, and associating types between packages and languages is a major sticking point.

Docker services alone require multiple configuration files for production, development, testing, and even debugging.I probably have 20 to 30 configuration and code files that pull the project together.Without Jsonnet, I wouldn't be able to cope.

Related Stop writing JSON by hand, this is a much easier way to handle config files These two formats are a lot more similar than their acronyms suggest.Posts 2 By  Bobby Jack Jsonnet is also super simple to learn.It looks like a blend of JSON and Python, which is familiar to most people.

I hit the ground running, and there was no upfront cost of picking up yet another skill, as there is with similar tools such as KCL or CUE.Google maintains Jsonnet too, and with widespread adoption, it's not going away.Some tips when using Jsonnet Consider a registry, but plan around its limitations Like most configuration languages, it's side-effect-free, meaning you can't touch the disk, make network requests, or similar.

I use Jsonnet as a central registry.Within a "config" directory at my repository root sit all my Jsonnet configuration and library files.Inside my regular code packages, where my vanilla config files live, I create similarly named Jsonnet files: repo_root/ ├── config/ │ ├── lib/ │ │ ├── math.jsonnet │ │ └── foo.jsonnet │ └── nx/ │ ├── foo.jsonnet │ └── bar.jsonnet └── apps/ ├── website/ │ ├── package.jsonnet │ ├── package.json │ ├── project.jsonnet │ ├── project.json │ ├── docker-compose.dev.yaml │ └── docker-compose.dev.jsonnet └── database/ ├── project.jsonnet └── project.json I use a task runner (like Taskfile, Mise, or Nx) to find the Jsonnet files in "apps" and then generate collocated configuration files from them.

Those files import "config" values and functions, which provide domain-specific data.Deals Save on developer software deals and subscription discounts Explore discounts on cloud services, IDEs, and AI tools to cut development costs.Find limited-time deals, subscription savings, and bundle offers across developer software, DevOps platforms, and productivity tools to streamline workflows.

Deals Explore Software, AI & Subscriptions Deals I'm still exploring how to configure a Jsonnet project, but it's important to note that Jsonnet does not hoist functions or "local" variables, which affects configuration value layout.However, it supports lazy evaluation, which we can leverage for more flexibility.Hoisting moves declarations to the top of their scope, so you can call a function (for example) before the line it's defined on.

It's found in JavaScript, among other languages.local x = y, y = "y"; // "y" referenced before declaration.{ foo: self.bar, // "bar" referenced before declaration.

bar: "bar", x: x, } Values inside objects and "local" variable blocks (first line in the code above) perform lazy evaluation, which means they're only processed at the moment they're needed.Consequently, order doesn't matter, so we can organize our values in almost any way.Claude Price $20 See at Claude Expand Collapse Jsonnet is easy to pick up, it's not going away, and it solves a real problem in larger projects: connecting disconnected components.

Why wouldn't I use it? Is it perfect? No, but it's good enough and flexible enough to shim and make it work in ways not initially intended.Jsonnet was the missing piece in my projects, and the fact that it can generate glue code from configuration values is an enormous plus.If you're interested in Jsonnet, check out their homepage, documentation, and GitHub repository for more information.

Related I stopped using VS Code after trying this less popular IDE (and it isn't Antigravity) I ditched VS Code for Zed instead of going for Google's Antigravity, and now the editor feels genuinely fast Posts 3 By  Jorge A.Aguilar

Read More
Related Posts