1
- # Copyright (c) 2022, 2023 , Oracle and/or its affiliates.
1
+ # Copyright (c) 2022, 2025 , Oracle and/or its affiliates.
2
2
# Licensed under the Universal Permissive License v 1.0 as shown at
3
3
# https://oss.oracle.com/licenses/upl.
4
4
5
5
from __future__ import annotations
6
6
7
7
import collections
8
+ import json
8
9
from abc import ABC , abstractmethod
9
10
from decimal import Decimal
10
11
from typing import Any , Callable , Dict , Final , Optional , Type , TypeVar , cast
29
30
30
31
MAGIC_BYTE : Final [bytes ] = b"\x15 "
31
32
32
- _type_to_alias : Final [Dict [Type [Any ], str ]] = dict ()
33
+ _type_to_alias : Final [Dict [Type [Any ], str ]] = {}
33
34
"""A mapping of proxied Python types to their alias."""
34
35
35
- _alias_to_type : Final [Dict [str , Type [Any ]]] = dict ()
36
+ _alias_to_type : Final [Dict [str , Type [Any ]]] = {}
36
37
"""A mapping of aliases to their proxied Python type."""
37
38
38
- _attribute_mappings : Final [Dict [Type [Any ], Dict [str , str ]]] = dict ()
39
+ _attribute_mappings : Final [Dict [Type [Any ], Dict [str , str ]]] = {}
39
40
"""A mapping of object attributes that require a different name when serialized/deserialized."""
40
41
41
- _attribute_mappings_rev : Final [Dict [Type [Any ], Dict [str , str ]]] = dict ()
42
+ _attribute_mappings_rev : Final [Dict [Type [Any ], Dict [str , str ]]] = {}
42
43
"""The same mapping as _attribute_mappings, but in reverse for deserialization."""
43
44
44
45
@@ -70,25 +71,43 @@ def __init__(self) -> None:
70
71
self ._pickler = JavaProxyPickler ()
71
72
self ._unpickler = JavaProxyUnpickler ()
72
73
74
+ def _to_json_from_object (self , obj : object ) -> str :
75
+ jsn = jsonpickle .encode (obj , context = self ._pickler )
76
+ return jsn
77
+
73
78
def serialize (self , obj : object ) -> bytes :
74
- jsn : str = jsonpickle . encode (obj , context = self . _pickler )
79
+ jsn : str = self . _to_json_from_object (obj )
75
80
b : bytes = MAGIC_BYTE + jsn .encode ()
76
81
return b
77
82
83
+ def _to_object_from_json (self , json_str : str ) -> T : # type: ignore
84
+ o = jsonpickle .decode (json_str , context = self ._unpickler )
85
+ return o
86
+
78
87
def deserialize (self , value : bytes ) -> T : # type: ignore
79
88
if isinstance (value , bytes ):
80
89
s = value .decode ()
81
90
if value .__len__ () == 0 : # empty string
82
91
return cast (T , None )
83
92
else :
84
93
if ord (s [0 ]) == ord (MAGIC_BYTE ):
85
- r = jsonpickle . decode (s [1 :], context = self . _unpickler )
94
+ r : T = self . _to_object_from_json (s [1 :])
86
95
return r
87
96
else :
88
97
raise ValueError ("Invalid JSON serialization format" )
89
98
else :
90
99
return cast (T , value )
91
100
101
+ def flatten_to_dict (self , o : object ) -> dict [Any , Any ]:
102
+ jsn = self ._to_json_from_object (o )
103
+ d = json .loads (jsn )
104
+ return d
105
+
106
+ def restore_to_object (self , the_dict : dict [Any , Any ]) -> T : # type: ignore
107
+ jsn = json .dumps (the_dict )
108
+ o : T = self ._to_object_from_json (jsn )
109
+ return o
110
+
92
111
93
112
class SerializerRegistry :
94
113
_singleton : SerializerRegistry
@@ -146,7 +165,7 @@ def _flatten_obj(self, obj: Any) -> dict[str, str | dict[str, list[dict[str, Any
146
165
if alias is not None :
147
166
marker = result .get (_JSON_PICKLE_OBJ , None )
148
167
if marker is not None :
149
- actual : dict [str , Any ] = dict ()
168
+ actual : dict [str , Any ] = {}
150
169
actual [_META_CLASS ] = alias
151
170
for key , value in result .items ():
152
171
# ignore jsonpickle specific content as well as protected keys
@@ -171,11 +190,11 @@ def _flatten_obj(self, obj: Any) -> dict[str, str | dict[str, list[dict[str, Any
171
190
and _META_VERSION not in value_
172
191
and _META_ENUM not in value_
173
192
):
174
- entries = list ()
193
+ entries = []
175
194
for key_inner , value_inner in value .items ():
176
195
entries .append ({_JSON_KEY : key_inner , _JSON_VALUE : value_inner })
177
196
178
- padding : dict [str , Any ] = dict ()
197
+ padding : dict [str , Any ] = {}
179
198
padding ["entries" ] = entries
180
199
value_ = padding
181
200
@@ -211,7 +230,7 @@ def _restore(self, obj: Any) -> Any:
211
230
metadata : Any = obj .get (_META_CLASS , None )
212
231
if metadata is not None :
213
232
type_ : Optional [Type [Any ]] = _type_for (metadata )
214
- actual : dict [Any , Any ] = dict ()
233
+ actual : dict [Any , Any ] = {}
215
234
if type_ is None :
216
235
if "map" in metadata .lower ():
217
236
for entry in obj [_JSON_ENTRIES ]:
@@ -245,7 +264,7 @@ def _restore(self, obj: Any) -> Any:
245
264
if len (obj ) == 1 :
246
265
entries = obj .get (_JSON_ENTRIES , None )
247
266
if entries is not None :
248
- actual = dict ()
267
+ actual = {}
249
268
for entry in obj [_JSON_ENTRIES ]:
250
269
actual [entry [_JSON_KEY ]] = entry [_JSON_VALUE ]
251
270
return super ().restore (actual , reset = False )
0 commit comments