Use TypeAdapter for Json serialization (#4183)

This commit is contained in:
Daniel Girtler 2026-02-03 22:27:51 +11:00 committed by GitHub
parent 0dddc7308d
commit 1d8352b466
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 15 additions and 63 deletions

View File

@ -77,7 +77,7 @@ class ArchConfig:
services: list[str] = field(default_factory=list)
custom_commands: list[str] = field(default_factory=list)
def unsafe_json(self) -> dict[str, Any]:
def unsafe_config(self) -> dict[str, Any]:
config: dict[str, list[UserSerialization] | str | None] = {}
if self.auth_config:
@ -94,7 +94,7 @@ class ArchConfig:
return config
def safe_json(self) -> dict[str, Any]:
def safe_config(self) -> dict[str, Any]:
config: Any = {
'version': self.version,
'script': self.script,

View File

@ -2,6 +2,9 @@ import json
import readline
import stat
from pathlib import Path
from typing import Any
from pydantic import TypeAdapter
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.translationhandler import tr
@ -10,7 +13,6 @@ from archinstall.tui.ui.result import ResultType
from .args import ArchConfig
from .crypt import encrypt
from .general import JSON, UNSAFE_JSON
from .output import debug, logger, warn
from .utils.util import get_password, prompt_dir
@ -40,12 +42,18 @@ class ConfigurationOutput:
return self._user_creds_file
def user_config_to_json(self) -> str:
out = self._config.safe_json()
return json.dumps(out, indent=4, sort_keys=True, cls=JSON)
config = self._config.safe_config()
adapter = TypeAdapter(dict[str, Any])
python_dict = adapter.dump_python(config)
return json.dumps(python_dict, indent=4, sort_keys=True)
def user_credentials_to_json(self) -> str:
out = self._config.unsafe_json()
return json.dumps(out, indent=4, sort_keys=True, cls=UNSAFE_JSON)
config = self._config.unsafe_config()
adapter = TypeAdapter(dict[str, Any])
python_dict = adapter.dump_python(config)
return json.dumps(python_dict, indent=4, sort_keys=True)
def write_debug(self) -> None:
debug(' -- Chosen configuration --')

View File

@ -1,9 +1,5 @@
import json
from datetime import date, datetime
from enum import Enum
from functools import lru_cache
from pathlib import Path
from typing import Any, override
from archinstall.lib.packages.packages import check_package_upgrade
@ -35,55 +31,3 @@ def running_from_host() -> bool:
"""
is_host = not Path('/run/archiso').exists()
return is_host
def jsonify(obj: Any, safe: bool = True) -> Any:
"""
Converts objects into json.dumps() compatible nested dictionaries.
Setting safe to True skips dictionary keys starting with a bang (!)
"""
compatible_types = str, int, float, bool
if isinstance(obj, dict):
return {
key: jsonify(value, safe)
for key, value in obj.items()
if isinstance(key, compatible_types) and not (isinstance(key, str) and key.startswith('!') and safe)
}
if isinstance(obj, Enum):
return obj.value
if hasattr(obj, 'json'):
# json() is a friendly name for json-helper, it should return
# a dictionary representation of the object so that it can be
# processed by the json library.
return jsonify(obj.json(), safe)
if isinstance(obj, datetime | date):
return obj.isoformat()
if isinstance(obj, list | set | tuple):
return [jsonify(item, safe) for item in obj]
if isinstance(obj, Path):
return str(obj)
if hasattr(obj, '__dict__'):
return vars(obj)
return obj
class JSON(json.JSONEncoder, json.JSONDecoder):
"""
A safe JSON encoder that will omit private information in dicts (starting with !)
"""
@override
def encode(self, o: Any) -> str:
return super().encode(jsonify(o))
class UNSAFE_JSON(json.JSONEncoder, json.JSONDecoder):
"""
UNSAFE_JSON will call/encode and keep private information in dicts (starting with !)
"""
@override
def encode(self, o: Any) -> str:
return super().encode(jsonify(o, safe=False))