nixos/shared/modules/home-manager/json2nix.nix
2026-02-12 16:20:21 -07:00

84 lines
2.7 KiB
Nix

# Provides json2nix command for converting JSON to Nix attribute set syntax
# Usage: wl-paste | json2nix | wl-copy
# json2nix < settings.json
{ config, lib, pkgs, ... }:
let
cfg = config.json2nix;
json2nixScript = pkgs.writeScriptBin "json2nix" ''
#!${pkgs.python3}/bin/python3
"""Convert JSON to Nix attribute set syntax.
Usage: wl-paste | json2nix | wl-copy
json2nix < settings.json
"""
import json
import sys
def to_nix(obj, indent=0):
"""Convert a Python object (from JSON) to Nix syntax."""
spaces = " " * indent
if obj is None:
return "null"
elif isinstance(obj, bool):
return "true" if obj else "false"
elif isinstance(obj, int):
return str(obj)
elif isinstance(obj, float):
# Ensure floats stay as floats (e.g., 1.0 not 1)
s = str(obj)
if '.' not in s and 'e' not in s.lower():
s += ".0"
return s
elif isinstance(obj, str):
# Escape special characters for Nix strings
escaped = obj.replace("\\", "\\\\")
escaped = escaped.replace('"', '\\"')
escaped = escaped.replace("\n", "\\n")
escaped = escaped.replace("\r", "\\r")
escaped = escaped.replace("\t", "\\t")
return f'"{escaped}"'
elif isinstance(obj, list):
if not obj:
return "[ ]"
items = []
for item in obj:
items.append(f"{spaces} {to_nix(item, indent + 1)}")
return "[\n" + "\n".join(items) + f"\n{spaces}]"
elif isinstance(obj, dict):
if not obj:
return "{ }"
items = []
for key, value in obj.items():
# Quote keys that aren't valid Nix identifiers
if not key.isidentifier() or key in ['if', 'then', 'else', 'let', 'in', 'with', 'rec', 'inherit', 'or', 'and']:
nix_key = f'"{key}"'
else:
nix_key = key
nix_value = to_nix(value, indent + 1)
items.append(f"{spaces} {nix_key} = {nix_value};")
return "{\n" + "\n".join(items) + f"\n{spaces}}}"
try:
data = json.load(sys.stdin)
print(to_nix(data))
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON - {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
'';
in
{
options.json2nix = {
enable = lib.mkEnableOption "json2nix command for converting JSON to Nix syntax";
};
config = lib.mkIf cfg.enable {
home.packages = [ json2nixScript ];
};
}