|
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