lib/types: add types json from pkgs.formats (#470842)

This commit is contained in:
Johannes Kirschbauer
2026-01-20 20:57:50 +00:00
committed by GitHub
5 changed files with 117 additions and 46 deletions
+24 -4
View File
@@ -58,12 +58,19 @@ logFailure() {
evalConfig() {
local attr=$1
shift
local script="import ./default.nix { modules = [ $* ];}"
local nix_args=()
if [ "${ABORT_ON_WARN-0}" = "1" ]; then
local-nix-instantiate --option abort-on-warn true -E "$script" -A "$attr"
else
local-nix-instantiate -E "$script" -A "$attr"
nix_args+=(--option abort-on-warn true)
fi
if [ "${STRICT_EVAL-0}" = "1" ]; then
nix_args+=(--strict)
fi
local script="import ./default.nix { modules = [ $* ];}"
local-nix-instantiate "${nix_args[@]}" -E "$script" -A "$attr"
}
reportFailure() {
@@ -247,6 +254,19 @@ checkConfigError 'A definition for option .* is not of type .fileset.. Definitio
checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err3 ./fileset.nix
checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err4 ./fileset.nix
# types.serializableValueWith
checkConfigOutput '^null$' config.nullableValue.null ./types.nix
checkConfigOutput '^true$' config.nullableValue.bool ./types.nix
checkConfigOutput '^1$' config.nullableValue.int ./types.nix
checkConfigOutput '^1.1$' config.nullableValue.float ./types.nix
checkConfigOutput '^"foo"$' config.nullableValue.str ./types.nix
checkConfigOutput '^".*/store.*"$' config.nullableValue.path ./types.nix
STRICT_EVAL=1 checkConfigOutput '^\{"foo":1\}$' config.nullableValue.attrs ./types.nix
STRICT_EVAL=1 checkConfigOutput '^\[\{"bar":\[1\]\}\]$' config.nullableValue.list ./types.nix
checkConfigError 'A definition for option .* is not of type .VAL value.. .*' config.nullableValue.lambda ./types.nix
checkConfigError 'A definition for option .* is not of type .VAL value.. .*' config.structuredValue.null ./types.nix
# Check boolean option.
checkConfigOutput '^false$' config.enable ./declare-enable.nix
checkConfigError 'The option .* does not exist. Definition values:\n\s*- In .*: true' config.enable ./define-enable.nix
+32
View File
@@ -16,6 +16,19 @@ in
options = {
pathInStore = mkOption { type = types.lazyAttrsOf types.pathInStore; };
externalPath = mkOption { type = types.lazyAttrsOf types.externalPath; };
# serializableValueWith
nullableValue = mkOption {
type = types.attrsOf (types.serializableValueWith { typeName = "VAL"; });
};
structuredValue = mkOption {
type = types.attrsOf (
types.serializableValueWith {
typeName = "VAL";
nullable = false;
}
);
};
assertions = mkOption { };
};
config = {
@@ -35,6 +48,22 @@ in
externalPath.ok1 = "/foo/bar";
externalPath.ok2 = "/";
# serializableValueWith { nullable = true; }
nullableValue.null = null; # null
nullableValue.bool = true; # bool
nullableValue.int = 1; # int
nullableValue.float = 1.1; # float
nullableValue.str = "foo"; # str
nullableValue.path = ./.; # path
nullableValue.attrs = {
foo = 1;
};
nullableValue.list = [ { bar = [ 1 ]; } ]; # list
nullableValue.lambda = x: x; # Error
# serializableValueWith { nullable = false; }
structuredValue.null = null; # Error
assertions =
with lib.types;
@@ -486,6 +515,9 @@ in
assert (unique { message = "custom"; } (listOf str)).description == "list of string";
assert (unique { message = "test"; } (either int str)).description == "signed integer or string";
assert (unique { message = "test"; } (listOf str)).description == "list of string";
# json & toml
assert json.description == "JSON value";
assert toml.description == "TOML value";
# done
"ok";
};
+39
View File
@@ -1437,6 +1437,45 @@ rec {
};
};
/**
Creates a value type suitable for serialization formats.
Parameters:
- typeName: String describing the format (e.g. "JSON", "YAML", "XML")
- nullable: Whether the structured value type allows `null` values.
Returns a type suitable for structured data formats that supports:
- Basic types: boolean, integer, float, string, path
- Complex types: attribute sets and lists
*/
serializableValueWith =
{
typeName,
nullable ? true,
}:
let
baseType = oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
];
valueType = (if nullable then nullOr baseType else baseType) // {
description = "${typeName} value";
};
in
valueType;
json = serializableValueWith { typeName = "JSON"; };
toml = serializableValueWith {
typeName = "TOML";
nullable = false;
};
# Either value of type `t1` or `t2`.
either =
t1: t2:
@@ -497,6 +497,20 @@ Composed types are types that take a type as parameter. `listOf
value of type *`to`*. Can be used to preserve backwards compatibility
of an option if its type was changed.
`types.json`
: A type representing JSON-compatible values. This includes `null`, booleans,
integers, floats, strings, paths, attribute sets, and lists.
Attribute sets and lists can be arbitrarily nested and contain any JSON-compatible
values.
`types.toml`
: A type representing TOML-compatible values. This includes booleans,
integers, floats, strings, paths, attribute sets, and lists.
Attribute sets and lists can be arbitrarily nested and contain any TOML-compatible
values.
## Submodule {#section-option-types-submodule}
`submodule` is a very powerful type that defines a set of sub-options
+8 -42
View File
@@ -40,6 +40,7 @@ let
;
inherit (lib.types)
serializableValueWith
attrsOf
atom
bool
@@ -58,38 +59,6 @@ let
submodule
;
/*
Creates a structured value type suitable for serialization formats.
Parameters:
- typeName: String describing the format (e.g. "JSON", "YAML", "XML")
- nullable: Whether the structured value type allows `null` values.
Returns a type suitable for structured data formats that supports:
- Basic types: boolean, integer, float, string, path
- Complex types: attribute sets and lists
*/
mkStructuredType =
{
typeName,
nullable ? true,
}:
let
baseType = oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
];
valueType = (if nullable then nullOr baseType else baseType) // {
description = "${typeName} value";
};
in
valueType;
# Attributes added accidentally in https://github.com/NixOS/nixpkgs/pull/335232 (2024-08-18)
# Deprecated in https://github.com/NixOS/nixpkgs/pull/415666 (2025-06)
allowAliases = pkgs.config.allowAliases or false;
@@ -162,7 +131,7 @@ optionalAttrs allowAliases aliases
{ }:
{
type = mkStructuredType { typeName = "JSON"; };
type = types.json;
generate =
name: value:
@@ -203,7 +172,7 @@ optionalAttrs allowAliases aliases
''
) { };
type = mkStructuredType { typeName = "YAML 1.1"; };
type = serializableValueWith { typeName = "YAML 1.1"; };
};
@@ -226,7 +195,7 @@ optionalAttrs allowAliases aliases
''
) { };
type = mkStructuredType { typeName = "YAML 1.2"; };
type = serializableValueWith { typeName = "YAML 1.2"; };
};
@@ -487,10 +456,7 @@ optionalAttrs allowAliases aliases
{ }:
json { }
// {
type = mkStructuredType {
typeName = "TOML";
nullable = false;
};
type = types.toml;
generate =
name: value:
@@ -523,7 +489,7 @@ optionalAttrs allowAliases aliases
{ }:
json { }
// {
type = mkStructuredType { typeName = "CDN"; };
type = serializableValueWith { typeName = "CDN"; };
generate =
name: value:
@@ -938,7 +904,7 @@ optionalAttrs allowAliases aliases
pythonVars =
{ }:
{
type = attrsOf (mkStructuredType {
type = attrsOf (serializableValueWith {
typeName = "Python";
});
@@ -1020,7 +986,7 @@ optionalAttrs allowAliases aliases
}:
if format == "badgerfish" then
{
type = mkStructuredType { typeName = "XML"; };
type = serializableValueWith { typeName = "XML"; };
generate =
name: value: