|
14 | 14 | from pydantic.types import SecretBytes, SecretStr |
15 | 15 |
|
16 | 16 | from aws_lambda_powertools.event_handler.openapi.compat import _model_dump |
| 17 | +from aws_lambda_powertools.event_handler.openapi.exceptions import SerializationError |
17 | 18 | from aws_lambda_powertools.event_handler.openapi.types import IncEx |
18 | 19 |
|
19 | 20 | """ |
@@ -69,88 +70,94 @@ def jsonable_encoder( # noqa: PLR0911 |
69 | 70 | if exclude is not None and not isinstance(exclude, (set, dict)): |
70 | 71 | exclude = set(exclude) |
71 | 72 |
|
72 | | - # Pydantic models |
73 | | - if isinstance(obj, BaseModel): |
74 | | - return _dump_base_model( |
75 | | - obj=obj, |
76 | | - include=include, |
77 | | - exclude=exclude, |
78 | | - by_alias=by_alias, |
79 | | - exclude_unset=exclude_unset, |
80 | | - exclude_none=exclude_none, |
81 | | - exclude_defaults=exclude_defaults, |
82 | | - ) |
| 73 | + try: |
| 74 | + # Pydantic models |
| 75 | + if isinstance(obj, BaseModel): |
| 76 | + return _dump_base_model( |
| 77 | + obj=obj, |
| 78 | + include=include, |
| 79 | + exclude=exclude, |
| 80 | + by_alias=by_alias, |
| 81 | + exclude_unset=exclude_unset, |
| 82 | + exclude_none=exclude_none, |
| 83 | + exclude_defaults=exclude_defaults, |
| 84 | + ) |
83 | 85 |
|
84 | | - # Dataclasses |
85 | | - if dataclasses.is_dataclass(obj): |
86 | | - obj_dict = dataclasses.asdict(obj) |
87 | | - return jsonable_encoder( |
88 | | - obj_dict, |
89 | | - include=include, |
90 | | - exclude=exclude, |
91 | | - by_alias=by_alias, |
92 | | - exclude_unset=exclude_unset, |
93 | | - exclude_defaults=exclude_defaults, |
94 | | - exclude_none=exclude_none, |
95 | | - ) |
| 86 | + # Dataclasses |
| 87 | + if dataclasses.is_dataclass(obj): |
| 88 | + obj_dict = dataclasses.asdict(obj) |
| 89 | + return jsonable_encoder( |
| 90 | + obj_dict, |
| 91 | + include=include, |
| 92 | + exclude=exclude, |
| 93 | + by_alias=by_alias, |
| 94 | + exclude_unset=exclude_unset, |
| 95 | + exclude_defaults=exclude_defaults, |
| 96 | + exclude_none=exclude_none, |
| 97 | + ) |
96 | 98 |
|
97 | | - # Enums |
98 | | - if isinstance(obj, Enum): |
99 | | - return obj.value |
| 99 | + # Enums |
| 100 | + if isinstance(obj, Enum): |
| 101 | + return obj.value |
100 | 102 |
|
101 | | - # Paths |
102 | | - if isinstance(obj, PurePath): |
103 | | - return str(obj) |
| 103 | + # Paths |
| 104 | + if isinstance(obj, PurePath): |
| 105 | + return str(obj) |
104 | 106 |
|
105 | | - # Scalars |
106 | | - if isinstance(obj, (str, int, float, type(None))): |
107 | | - return obj |
| 107 | + # Scalars |
| 108 | + if isinstance(obj, (str, int, float, type(None))): |
| 109 | + return obj |
108 | 110 |
|
109 | | - # Dictionaries |
110 | | - if isinstance(obj, dict): |
111 | | - return _dump_dict( |
112 | | - obj=obj, |
113 | | - include=include, |
114 | | - exclude=exclude, |
115 | | - by_alias=by_alias, |
116 | | - exclude_none=exclude_none, |
117 | | - exclude_unset=exclude_unset, |
118 | | - ) |
| 111 | + # Dictionaries |
| 112 | + if isinstance(obj, dict): |
| 113 | + return _dump_dict( |
| 114 | + obj=obj, |
| 115 | + include=include, |
| 116 | + exclude=exclude, |
| 117 | + by_alias=by_alias, |
| 118 | + exclude_none=exclude_none, |
| 119 | + exclude_unset=exclude_unset, |
| 120 | + ) |
| 121 | + |
| 122 | + # Sequences |
| 123 | + if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)): |
| 124 | + return _dump_sequence( |
| 125 | + obj=obj, |
| 126 | + include=include, |
| 127 | + exclude=exclude, |
| 128 | + by_alias=by_alias, |
| 129 | + exclude_none=exclude_none, |
| 130 | + exclude_defaults=exclude_defaults, |
| 131 | + exclude_unset=exclude_unset, |
| 132 | + ) |
119 | 133 |
|
120 | | - # Sequences |
121 | | - if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)): |
122 | | - return _dump_sequence( |
| 134 | + # Other types |
| 135 | + if type(obj) in ENCODERS_BY_TYPE: |
| 136 | + return ENCODERS_BY_TYPE[type(obj)](obj) |
| 137 | + |
| 138 | + for encoder, classes_tuple in encoders_by_class_tuples.items(): |
| 139 | + if isinstance(obj, classes_tuple): |
| 140 | + return encoder(obj) |
| 141 | + |
| 142 | + # Use custom serializer if present |
| 143 | + if custom_serializer: |
| 144 | + return custom_serializer(obj) |
| 145 | + |
| 146 | + # Default |
| 147 | + return _dump_other( |
123 | 148 | obj=obj, |
124 | 149 | include=include, |
125 | 150 | exclude=exclude, |
126 | 151 | by_alias=by_alias, |
127 | 152 | exclude_none=exclude_none, |
128 | | - exclude_defaults=exclude_defaults, |
129 | 153 | exclude_unset=exclude_unset, |
| 154 | + exclude_defaults=exclude_defaults, |
130 | 155 | ) |
131 | | - |
132 | | - # Other types |
133 | | - if type(obj) in ENCODERS_BY_TYPE: |
134 | | - return ENCODERS_BY_TYPE[type(obj)](obj) |
135 | | - |
136 | | - for encoder, classes_tuple in encoders_by_class_tuples.items(): |
137 | | - if isinstance(obj, classes_tuple): |
138 | | - return encoder(obj) |
139 | | - |
140 | | - # Use custom serializer if present |
141 | | - if custom_serializer: |
142 | | - return custom_serializer(obj) |
143 | | - |
144 | | - # Default |
145 | | - return _dump_other( |
146 | | - obj=obj, |
147 | | - include=include, |
148 | | - exclude=exclude, |
149 | | - by_alias=by_alias, |
150 | | - exclude_none=exclude_none, |
151 | | - exclude_unset=exclude_unset, |
152 | | - exclude_defaults=exclude_defaults, |
153 | | - ) |
| 156 | + except ValueError as exc: |
| 157 | + raise SerializationError( |
| 158 | + f"Unable to serialize the object {obj} as it is not a supported type. Error details: {exc}", |
| 159 | + "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#serializing-objects", |
| 160 | + ) from exc |
154 | 161 |
|
155 | 162 |
|
156 | 163 | def _dump_base_model( |
|
0 commit comments