1+ import json
2+
3+ # # # # # # # # # # # # # # # # # # # # # # #
4+ # # # # # # # # # # Loads # # # # # # # # # #
5+ # # # # # # # # # # # # # # # # # # # # # # #
6+ """
7+ >>> INPUT: '{"author": "truocphan", "version": "22.3.3", "version": "latest", "release": [{"version": "22.3.3", "version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
8+
9+ <<< OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': 'latest', 'release': [{'version': '22.3.3', 'version{{{_2_}}}': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
10+ """
11+ def loads (Jstr , dupSign_start = "{" , dupSign_end = "}" , _isDebug_ = False ):
12+ import re
13+ from collections import OrderedDict
14+ import traceback
15+
16+ def __convert_Jloads_to_Jobj (Jloads , Jobj ):
17+ if type (Jloads ) == OrderedDict :
18+ for k in Jloads .keys ():
19+ _key = re .split (dupSign_start_escape_regex * 3 + "_\d+_" + dupSign_end_escape_regex * 3 + "$" , k )[0 ]
20+
21+ if _key not in Jobj .keys ():
22+ if type (Jloads [k ]) not in [list , OrderedDict ]:
23+ Jobj [_key ] = Jloads [k ]
24+ else :
25+ if type (Jloads [k ]) == list :
26+ Jobj [_key ] = list ()
27+ else :
28+ Jobj [_key ] = OrderedDict ()
29+
30+ __convert_Jloads_to_Jobj (Jloads [k ], Jobj [_key ])
31+ else :
32+ countObj = len ([i for i in Jobj .keys () if _key == re .split (dupSign_start_escape_regex * 3 + "_\d+_" + dupSign_end_escape_regex * 3 + "$" , i )[0 ]])
33+ if type (Jloads [k ]) not in [list , OrderedDict ]:
34+ Jobj [_key + dupSign_start * 3 + "_" + str (countObj + 1 )+ "_" + dupSign_end * 3 ] = Jloads [k ]
35+ else :
36+ if type (Jloads [k ]) == list :
37+ Jobj [_key + dupSign_start * 3 + "_" + str (countObj + 1 )+ "_" + dupSign_end * 3 ] = list ()
38+ else :
39+ Jobj [_key + dupSign_start * 3 + "_" + str (countObj + 1 )+ "_" + dupSign_end * 3 ] = OrderedDict ()
40+
41+ __convert_Jloads_to_Jobj (Jloads [k ], Jobj [_key + dupSign_start * 3 + "_" + str (countObj + 1 )+ "_" + dupSign_end * 3 ])
42+ elif type (Jloads ) == list :
43+ for i in range (len (Jloads )):
44+ if type (Jloads [i ]) not in [list , OrderedDict ]:
45+ Jobj .append (Jloads [i ])
46+ else :
47+ if type (Jloads [i ]) == list :
48+ Jobj .append (list ())
49+ else :
50+ Jobj .append (OrderedDict ())
51+
52+ __convert_Jloads_to_Jobj (Jloads [i ], Jobj [i ])
53+
54+ try :
55+ Jloads = json .loads (Jstr , object_pairs_hook = OrderedDict )
56+
57+ if type (Jloads ) in [list , OrderedDict ] and len (Jloads ) > 0 :
58+ try :
59+ if type (dupSign_start ) not in [str , unicode ] or len (dupSign_start ) == 0 : dupSign_start = "{"
60+ except Exception as e :
61+ if type (dupSign_start ) != str or len (dupSign_start ) == 0 : dupSign_start = "{"
62+
63+ dupSign_start_escape = "" .join (["\\ \\ u" + hex (ord (c ))[2 :].zfill (4 ) for c in dupSign_start ])
64+
65+ dupSign_start_escape_regex = re .escape (dupSign_start )
66+
67+
68+ try :
69+ if type (dupSign_end ) not in [str , unicode ] or len (dupSign_end ) == 0 : dupSign_end = "}"
70+ except Exception as e :
71+ if type (dupSign_end ) != str or len (dupSign_end ) == 0 : dupSign_end = "}"
72+
73+ dupSign_end_escape = "" .join (["\\ \\ u" + hex (ord (c ))[2 :].zfill (4 ) for c in dupSign_end ])
74+
75+ dupSign_end_escape_regex = re .escape (dupSign_end )
76+
77+
78+ Jstr = re .sub (r'\\\\' , '\x00 \x01 ' , Jstr )
79+ Jstr = re .sub (r'\\"' , '\x02 \x03 ' , Jstr )
80+ Jstr = re .sub (r'"([^"]*)"[\s\t\r\n]*([,\]}])' , '\x04 \x05 \\ 1\x04 \x05 \\ 2' , Jstr )
81+
82+
83+ Jstr = re .sub (r'"([^"]+)"[\s\t\r\n]*:' , r'"\1{dupSign_start}_dupSign_{dupSign_end}":' .format (dupSign_start = dupSign_start_escape * 3 , dupSign_end = dupSign_end_escape * 3 ), Jstr )
84+
85+ Jstr = re .sub (r'""[\s\t\r\n]*:' , '"{dupSign_start}_dupSign_{dupSign_end}":' .format (dupSign_start = dupSign_start_escape * 3 , dupSign_end = dupSign_end_escape * 3 ), Jstr )
86+
87+ i = 0
88+ while re .search (r'{dupSign_start}_dupSign_{dupSign_end}"[\s\t\r\n]*:' .format (dupSign_start = dupSign_start_escape * 3 , dupSign_end = dupSign_end_escape * 3 ), Jstr ):
89+ Jstr = re .sub (r'{dupSign_start}_dupSign_{dupSign_end}"[\s\t\r\n]*:' .format (dupSign_start = dupSign_start_escape * 3 , dupSign_end = dupSign_end_escape * 3 ), dupSign_start_escape * 3 + "_" + str (i )+ "_" + dupSign_end_escape * 3 + '":' , Jstr , 1 )
90+ i += 1
91+
92+ Jstr = re .sub ('\x00 \x01 ' , r'\\\\' , Jstr )
93+ Jstr = re .sub ('\x02 \x03 ' , r'\\"' , Jstr )
94+ Jstr = re .sub ('\x04 \x05 ' , r'"' , Jstr )
95+
96+ Jloads = json .loads (Jstr , object_pairs_hook = OrderedDict )
97+
98+ if type (Jloads ) == list :
99+ Jobj = list ()
100+ else :
101+ Jobj = OrderedDict ()
102+
103+ __convert_Jloads_to_Jobj (Jloads , Jobj )
104+
105+ return Jobj
106+ else :
107+ return Jloads
108+ except :
109+ if _isDebug_ : traceback .print_exc ()
110+ return None
111+ # # # # # # # # # # # # # # # # # # # # # # #
112+ # # # # # # # # # # # # # # # # # # # # # # #
113+ # # # # # # # # # # # # # # # # # # # # # # #
114+
115+
116+
117+
118+
119+ # # # # # # # # # # # # # # # # # # # # # # #
120+ # # # # # # # # # # Dumps # # # # # # # # # #
121+ # # # # # # # # # # # # # # # # # # # # # # #
122+ """
123+ >>> INPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': '22.3.14', 'release': [{'version': '22.3.3', 'version{{{_2_}}}': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
124+
125+ <<< OUTPUT: '{"author": "truocphan", "version": "22.3.3", "version": "22.3.14", "release": [{"version": "22.3.3", "version": "latest"}], "snapshot": {"author": "truocphan", "version": "22.3.3", "release": [{"version": "latest"}]}}'
126+ """
127+ def dumps (Jobj , dupSign_start = "{" , dupSign_end = "}" , _isDebug_ = False , skipkeys = False , ensure_ascii = True , check_circular = True , allow_nan = True , cls = None , indent = None , separators = None , default = None , sort_keys = False ):
128+ import re
129+ from collections import OrderedDict
130+ import traceback
131+
132+ try :
133+ if type (Jobj ) in [list , dict , tuple , OrderedDict ] and len (Jobj ) > 0 :
134+ try :
135+ if type (dupSign_start ) not in [str , unicode ]: dupSign_start = "{"
136+ except Exception as e :
137+ if type (dupSign_start ) != str : dupSign_start = "{"
138+
139+ dupSign_start_escape_regex = re .escape (json .dumps ({dupSign_start :"" })[2 :- 6 ])
140+
141+
142+ try :
143+ if type (dupSign_end ) not in [str , unicode ]: dupSign_end = "}"
144+ except Exception as e :
145+ if type (dupSign_end ) != str : dupSign_end = "}"
146+
147+ dupSign_end_escape_regex = re .escape (json .dumps ({dupSign_end :"" })[2 :- 6 ])
148+
149+
150+ if len (dupSign_start ) == 0 and len (dupSign_end ) == 0 :
151+ return json .dumps (Jobj , skipkeys = skipkeys , ensure_ascii = ensure_ascii , check_circular = check_circular , allow_nan = allow_nan , cls = cls , indent = indent , separators = separators , default = default , sort_keys = sort_keys )
152+ else :
153+ return re .sub (r'{dupSign_start}_\d+_{dupSign_end}":' .format (dupSign_start = dupSign_start_escape_regex * 3 , dupSign_end = dupSign_end_escape_regex * 3 ), '":' , json .dumps (Jobj , skipkeys = skipkeys , ensure_ascii = ensure_ascii , check_circular = check_circular , allow_nan = allow_nan , cls = cls , indent = indent , separators = separators , default = default , sort_keys = sort_keys ))
154+ else :
155+ return json .dumps (Jobj , skipkeys = skipkeys , ensure_ascii = ensure_ascii , check_circular = check_circular , allow_nan = allow_nan , cls = cls , indent = indent , separators = separators , default = default , sort_keys = sort_keys )
156+ except :
157+ if _isDebug_ : traceback .print_exc ()
158+ return None
159+ # # # # # # # # # # # # # # # # # # # # # # #
160+ # # # # # # # # # # # # # # # # # # # # # # #
161+ # # # # # # # # # # # # # # # # # # # # # # #
162+
163+
164+
165+
166+
167+ # # # # # # # # # # # # # # # # # # # # # # #
168+ # # # # # # # # # Flatten # # # # # # # # # #
169+ # # # # # # # # # # # # # # # # # # # # # # #
170+ """
171+ >>> INPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': '22.3.14', 'release': [{'version': '22.3.3', 'version{{{_2_}}}': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': 'latest'}]}}
172+
173+ <<< OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': '22.3.14', 'release||$0$||version': '22.3.3', 'release||$0$||version{{{_2_}}}': 'latest', 'snapshot||author': 'truocphan', 'snapshot||version': '22.3.3', 'snapshot||release||$0$||version': 'latest'}
174+ """
175+ def flatten (Jobj , separator = "||" , parse_index = "$" , _isDebug_ = False ):
176+ from collections import OrderedDict
177+ import traceback
178+
179+ Jflat = OrderedDict ()
180+
181+ def __convert_Jobj_to_Jflat (Jobj , key = None ):
182+ if type (Jobj ) in [dict , OrderedDict ]:
183+ if len (Jobj ) == 0 :
184+ Jflat [key ] = OrderedDict ()
185+ else :
186+ for k ,v in Jobj .items ():
187+ _Jobj = v
188+ _key = "{key}{separator}{k}" .format (key = key ,separator = separator ,k = k ) if key != None else "{k}" .format (k = k )
189+
190+ __convert_Jobj_to_Jflat (_Jobj , _key )
191+ elif type (Jobj ) == list :
192+ if len (Jobj ) == 0 :
193+ Jflat [key ] = list ()
194+ else :
195+ for i ,v in enumerate (Jobj ):
196+ _Jobj = v
197+ _key = "{key}{separator}{parse_index}{i}{parse_index}" .format (key = key , separator = separator , parse_index = parse_index , i = i ) if key != None else "{parse_index}{i}{parse_index}" .format (parse_index = parse_index , i = i )
198+
199+ __convert_Jobj_to_Jflat (_Jobj , _key )
200+ else :
201+ Jflat [key ] = Jobj
202+
203+ try :
204+ if type (Jobj ) in [list , dict , OrderedDict ]:
205+ if len (Jobj ) == 0 :
206+ if type (Jobj ) == list :
207+ if _isDebug_ : print ("+ [DEBUG::flatten] Unable to Flatten an empty List" )
208+ return None
209+ else :
210+ return Jflat
211+ else :
212+ try :
213+ if type (separator ) not in [str , unicode ] or len (separator ) == 0 : separator = "||"
214+ except Exception as e :
215+ if type (separator ) != str or len (separator ) == 0 : separator = "||"
216+
217+ try :
218+ if type (parse_index ) not in [str , unicode ] or len (parse_index ) == 0 : parse_index = "$"
219+ except Exception as e :
220+ if type (parse_index ) != str or len (parse_index ) == 0 : parse_index = "$"
221+
222+ __convert_Jobj_to_Jflat (Jobj )
223+
224+ return Jflat
225+ else :
226+ if _isDebug_ : print ("+ [DEBUG::flatten] Unable to Flatten the {datatype} Object: \" {value}\" " .format (datatype = type (Jobj ), value = Jobj ))
227+ return None
228+ except :
229+ if _isDebug_ : traceback .print_exc ()
230+ return None
231+ # # # # # # # # # # # # # # # # # # # # # # #
232+ # # # # # # # # # # # # # # # # # # # # # # #
233+ # # # # # # # # # # # # # # # # # # # # # # #
234+
235+
236+
237+
238+
239+ # # # # # # # # # # # # # # # # # # # # # # #
240+ # # # # # # # # # Unflatten # # # # # # # # #
241+ # # # # # # # # # # # # # # # # # # # # # # #
242+ """
243+ >>> INPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': '22.3.14', 'release||$0$||version': '22.3.3', 'release||$0$||version{{{_2_}}}': 'latest', 'snapshot||author': 'truocphan', 'snapshot||version': '22.3.3', 'snapshot||release||$0$||version': '22.3.14'}
244+
245+ <<< OUTPUT: {'author': 'truocphan', 'version': '22.3.3', 'version{{{_2_}}}': '22.3.14', 'release': [{'version': '22.3.3', 'version{{{_2_}}}': 'latest'}], 'snapshot': {'author': 'truocphan', 'version': '22.3.3', 'release': [{'version': '22.3.14'}]}}
246+ """
247+ def unflatten (Jflat , separator = "||" , parse_index = "$" , _isDebug_ = False ):
248+ import re
249+ from collections import OrderedDict
250+ import traceback
251+
252+ try :
253+ if type (Jflat ) in [dict , OrderedDict ]:
254+ if len (Jflat ) == 0 :
255+ return OrderedDict ()
256+ else :
257+ Jobj = list () if len ([k for k in Jflat .keys () if re .compile ("^" + re .escape (parse_index )+ "\d+" + re .escape (parse_index )+ "$" ).match (str (k ).split (separator )[0 ])]) == len (Jflat .keys ()) else OrderedDict ()
258+
259+ for k , v in Jflat .items ():
260+ Jtmp = Jobj
261+ Jkeys = k .split (separator )
262+
263+ for count , (Jkey , next_Jkeys ) in enumerate (zip (Jkeys , Jkeys [1 :] + [v ]), 1 ):
264+ v = next_Jkeys if count == len (Jkeys ) else list () if re .compile ("^" + re .escape (parse_index )+ "\d+" + re .escape (parse_index )+ "$" ).match (next_Jkeys ) else OrderedDict ()
265+
266+ if type (Jtmp ) == list :
267+ Jkey = int (re .compile (re .escape (parse_index )+ "(\d+)" + re .escape (parse_index )).match (Jkey ).group (1 ))
268+
269+ while Jkey >= len (Jtmp ):
270+ Jtmp .append (v )
271+
272+ elif Jkey not in Jtmp :
273+ Jtmp [Jkey ] = v
274+
275+ Jtmp = Jtmp [Jkey ]
276+
277+ return Jobj
278+ else :
279+ if _isDebug_ : print ("+ [DEBUG::unflatten] Unable to Unflatten the {datatype} Object: \" {value}\" " .format (datatype = type (Jflat ), value = Jflat ))
280+ return None
281+ except :
282+ if _isDebug_ : traceback .print_exc ()
283+ return None
284+ # # # # # # # # # # # # # # # # # # # # # # #
285+ # # # # # # # # # # # # # # # # # # # # # # #
286+ # # # # # # # # # # # # # # # # # # # # # # #
0 commit comments