Coverage for python/lsst/daf/butler/core/json.py: 52%
27 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-08-12 09:20 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-08-12 09:20 +0000
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22from __future__ import annotations
24__all__ = ("to_json_generic", "from_json_generic", "to_json_pydantic", "from_json_pydantic")
26import json
27from typing import TYPE_CHECKING, Any, Protocol, Type
29if TYPE_CHECKING:
30 from ..registry import Registry
31 from .dimensions import DimensionUniverse
34class SupportsSimple(Protocol):
35 """Protocol defining the methods required to support the standard
36 serialization using "simple" methods names.
37 """
39 _serializedType: Type
41 def to_simple(self, minimal: bool) -> Any:
42 ...
44 @classmethod
45 def from_simple(
46 cls, simple: Any, universe: DimensionUniverse | None = None, registry: Registry | None = None
47 ) -> SupportsSimple:
48 ...
51def to_json_pydantic(self: SupportsSimple, minimal: bool = False) -> str:
52 """Convert this class to JSON assuming that the ``to_simple()`` returns
53 a pydantic model.
55 """
56 return self.to_simple(minimal=minimal).model_dump_json(exclude_defaults=True, exclude_unset=True)
59def from_json_pydantic(
60 cls: type[SupportsSimple],
61 json_str: str,
62 universe: DimensionUniverse | None = None,
63 registry: Registry | None = None,
64) -> SupportsSimple:
65 """Convert from JSON to a pydantic model."""
66 simple = cls._serializedType.model_validate_json(json_str)
67 try:
68 return cls.from_simple(simple, universe=universe, registry=registry)
69 except AttributeError as e:
70 raise AttributeError(f"JSON deserialization requires {cls} has a from_simple() class method") from e
73def to_json_generic(self: SupportsSimple, minimal: bool = False) -> str:
74 """Convert this class to JSON form.
76 The class type is not recorded in the JSON so the JSON decoder
77 must know which class is represented.
79 Parameters
80 ----------
81 minimal : `bool`, optional
82 Use minimal serialization. Requires Registry to convert
83 back to a full type.
85 Returns
86 -------
87 json : `str`
88 The class in JSON string format.
89 """
90 # For now use the core json library to convert a dict to JSON
91 # for us.
92 return json.dumps(self.to_simple(minimal=minimal))
95def from_json_generic(
96 cls: type[SupportsSimple],
97 json_str: str,
98 universe: DimensionUniverse | None = None,
99 registry: Registry | None = None,
100) -> SupportsSimple:
101 """Return new class from JSON string.
103 Converts a JSON string created by `to_json` and return
104 something of the supplied class.
106 Parameters
107 ----------
108 json_str : `str`
109 Representation of the dimensions in JSON format as created
110 by `to_json()`.
111 universe : `DimensionUniverse`, optional
112 The special graph of all known dimensions. Passed directly
113 to `from_simple()`.
114 registry : `lsst.daf.butler.Registry`, optional
115 Registry to use to convert simple name of a DatasetType to
116 a full `DatasetType`. Passed directly to `from_simple()`.
118 Returns
119 -------
120 constructed : Any
121 Newly-constructed object.
122 """
123 simple = json.loads(json_str)
124 try:
125 return cls.from_simple(simple, universe=universe, registry=registry)
126 except AttributeError as e:
127 raise AttributeError(f"JSON deserialization requires {cls} has a from_simple() class method") from e