Contents

原创作品,允许转载。转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。

来到网易的第三天,我还是在Python的学习阶段,不过对Python一些理论性的东西已经有所理解。与此同时,主管也有给我一些小练习,让我边做边熟悉。是的,学习一种新的编程语言最有效率的方法就是边看书边打代码做小练习,这在我之前的学习中也深有体会。

在此顺便记录一下小练习JSON Parser的代码:初学勿喷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# -*- coding: utf-8 -*-
import string
class JsonParser:
def __init__(self):
self.data_json = None
# JSON type: null, true and false.
__list_jdt = [u'null', u'true', u'false']
# Read a string JSON data into the class, with no return value.
def load(self, s):
print(u'[INFO] Load JSON string.')
json_type = JsonParser.__get_json_obj_type(s)
if json_type == list:
self.data_json = list()
elif json_type == dict:
self.data_json = dict()
self.__build_json_data(self.data_json, self.__parse_json_objects(s), json_type)
# Reference to the dictionary data and return the JSON string.
def dump(self):
return str(self.data_json)
# Build with parent and child relationship, to align the JSON data structure, with no return value.
def __build_json_data(self, parent, obj, typ):
if typ == dict:
count_bb = 0
count_sb = 0
obj_key = ''
obj_value = []
flg_d = True
for i in range(len(obj)):
if flg_d:
if obj[i] == ':':
flg_d = not flg_d
obj_key = obj[i - 1].replace('"', '')
else:
count_bb, count_sb = JsonParser.__cal_brackets(obj[i], count_bb, count_sb)
obj_value.append(obj[i])
if count_bb + count_sb == 0:
flg_d = not flg_d
self.__build_dict(parent, obj_key, obj_value)
obj_key = ''
obj_value = []
elif typ == list:
count_bb = 0
count_sb = 0
list_obj = []
del obj[0]
del obj[len(obj) - 1]
for i in range(len(obj)):
count_bb, count_sb = JsonParser.__cal_brackets(obj[i], count_bb, count_sb)
list_obj.append(obj[i])
if count_bb + count_sb == 0:
self.__build_list(parent, list_obj)
list_obj = []
# Build list data
def __build_list(self, parent, list_obj):
if list_obj[0] != ',':
if list_obj[0] == '{':
parent.append(list_obj)
parent[len(parent) - 1] = dict()
self.__build_json_data(parent[len(parent) - 1], list_obj, dict)
elif list_obj[0] == '[':
parent.append(list_obj)
parent[len(parent) - 1] = list()
self.__build_json_data(parent[len(parent) - 1], list_obj, list)
# Build dictionary data
def __build_dict(self, parent, obj_key, obj_value):
if obj_value[0] == '{':
parent[obj_key] = dict()
self.__build_json_data(parent[obj_key], obj_value, dict)
elif obj_value[0] == '[':
parent[obj_key] = list()
self.__build_json_data(parent[obj_key], obj_value, list)
elif len(obj_value) == 1:
if obj_value[0] in self.__list_jdt:
if obj_value[0] == self.__list_jdt[0]:
parent[obj_key] = None
elif obj_value[0] == self.__list_jdt[1]:
parent[obj_key] = True
elif obj_value[0] == self.__list_jdt[2]:
parent[obj_key] = False
else:
raise JsonValueError(u'JSON value exception.', obj_value[0])
elif obj_value[0][0] == '"':
parent[obj_key] = obj_value[0].replace('"', '')
elif '.' in obj_value[0]:
try:
parent[obj_key] = string.atof(obj_value[0])
except ValueError:
raise JsonValueError(u'Invalid literal JSON value for float.', obj_value[0])
except:
raise JsonError(u'[ERROR] Unknown Json Error.')
else:
try:
parent[obj_key] = string.atoi(obj_value[0])
except ValueError:
raise JsonValueError(u'Invalid literal JSON value for int.', obj_value[0])
except:
raise JsonError(u'[ERROR] Unknown Json Error.')
else:
raise JsonFormatError(u'JSON format exception.')
# calculate the brackets
@staticmethod
def __cal_brackets(obj, count_bb, count_sb):
if obj == '{':
count_bb += 1
if obj == '}':
count_bb -= 1
if obj == '[':
count_sb += 1
if obj == ']':
count_sb -= 1
return count_bb, count_sb
# Return the quantity of quotes.
@staticmethod
def __count_quotes(s, flg):
count = 0
if flg == 0:
for cc in s:
if cc == '"':
count += 1
if flg == 1:
for cc in s:
if cc == '\'':
count += 1
return count
# Check if s is the JSON data type.
def __is_json_type(self, s):
if s[0] == '"':
return True
elif s in self.__list_jdt:
return True
else:
return False
# Parse the JSON string data to the object list.
def __parse_json_objects(self, str_json):
list_json = []
str_tmp = ''
for sgm_i in str_json:
if sgm_i == u'\n':
continue
if sgm_i != ' ':
if sgm_i == '{' or sgm_i == '}' or sgm_i == '[' or sgm_i == ']' or sgm_i == ':' or sgm_i == ',':
if str_tmp != '':
if str_tmp[0] == '\'' or str_tmp[len(str_tmp) - 1] == '\'':
raise JsonFormatError(
u'JSON standard does not allow single quoted strings. >>> ' + str_tmp)
if (str_tmp[0] == '"' and str_tmp[len(str_tmp) - 1] != '"') \
or (str_tmp[0] != '"' and str_tmp[len(str_tmp) - 1] == '"'):
raise JsonFormatError(u'JSON verification error, missing double quote. >>> ' + str_tmp)
elif not self.__is_json_type(str_tmp):
try:
if float(str_tmp) / 1 == float('inf') or float(str_tmp) / 1 == float('-inf'):
exit(1)
except ValueError:
print(u'[ERROR] JSON standard does not allow identifiers. >>> %s' % str_tmp)
exit(1)
except:
print(u'[ERROR] Upper limit of Python float type. >>> %s' % str_tmp)
exit(1)
if sgm_i == ':' and str_tmp[0] != '"':
raise JsonFormatError(
u'JSON standard allows only double quoted string as property key. >>> ' + str_tmp)
list_json.append(str_tmp)
str_tmp = ''
list_json.append(sgm_i)
else:
str_tmp = str_tmp + sgm_i
elif len(str_tmp) > 0 and str_tmp[0] == '"' and JsonParser.__count_quotes(str_tmp, 0) == 1:
str_tmp = str_tmp + sgm_i
return list_json
# To determine the JSON object type
@staticmethod
def __get_json_obj_type(str_json):
for ch in str_json:
if ch == u' ':
continue
elif ch == u'[':
return list
elif ch == u'{':
return dict
else:
raise JsonInvalidKeywordError(
u'JSON standard not allow to begin with this character (root character). >>> %s', ch)
# Parse None, True, False to JSON value
@staticmethod
def __parse_jdt(s):
if s == 'None':
return 'null'
if s == 'True':
return 'true'
if s == 'False':
return 'false'
return s
# Parse the dictionary to JSON string.
def __dict_to_json_str(self, dict_json):
str_json = str(dict_json)
list_json = []
str_tmp = ''
for sgm_i in str_json:
if sgm_i == u'\n':
continue
if sgm_i != ' ':
if sgm_i == '{' or sgm_i == '}' or sgm_i == '[' or sgm_i == ']' or sgm_i == ':' or sgm_i == ',':
if str_tmp != '':
if str_tmp[0] == '\'' or str_tmp[len(str_tmp) - 1] == '\'':
str_tmp = '"' + str_tmp[1:len(str_tmp) - 1] + '"'
if sgm_i == ':' and str_tmp[0] != '"':
raise JsonFormatError(
u'JSON standard allows only double quoted string as property key. >>> Key: ' + str_tmp)
if list_json[len(list_json) - 1] == ':':
str_tmp = self.__parse_jdt(str_tmp)
if not self.__is_json_type(str_tmp):
try:
if float(str_tmp) / 1 == float('inf') or float(str_tmp) / 1 == float('-inf'):
exit(1)
except ValueError:
print(u'[ERROR] JSON standard does not allow identifiers. >>> %s' % str_tmp)
exit(1)
except:
print(u'[ERROR] Upper limit of Python float type. >>> %s' % str_tmp)
exit(1)
list_json.append(str_tmp)
str_tmp = ''
list_json.append(sgm_i)
else:
str_tmp = str_tmp + sgm_i
elif len(str_tmp) > 0 and str_tmp[0] == '\'' and JsonParser.__count_quotes(str_tmp, 1) == 1:
str_tmp = str_tmp + sgm_i
str_tmp = ''
for sgm_j in list_json:
str_tmp += sgm_j
return str_tmp
# Deep copy a JSON object
def __deep_copy(self, obj):
if isinstance(obj, list):
return [self.__deep_copy(item) for item in obj]
elif isinstance(obj, dict):
return dict((key, self.__deep_copy(obj[key])) for key in obj)
return obj
# Load a external JSON file into json_dict.
def loadJson(self, f):
print(u'[INFO] Load the JSON file: %s' % f)
str_json = ''
file_json = open(f, 'r')
try:
while True:
line = file_json.readline()
if len(line) == 0:
break
str_json += line
except IOError:
print(u'[ERROR] IO error, please check!')
exit(1)
except:
print(u'[ERROR] Program exception!')
exit(1)
finally:
file_json.close()
self.load(str_json)
# Dump the class data into a JSON file, overwrite if file exist, failed if IO error.
def dumpJson(self, f):
print(u'[INFO] Dump to JSON file: %s' % f)
file_json = open(f, 'w')
try:
file_json.write(self.__dict_to_json_str(self.data_json))
except IOError:
print('[ERROR] IO error, please check!')
exit(1)
finally:
file_json.close()
# Load a object into class data and skip non-string type keys
def loadDict(self, d):
print(u'[INFO] Load dictionary.')
str_json = str(d)
str_tgt = ''
for i in range(len(str_json)):
if str_json[i] == '\'' and str_json[i - 1] != '\\':
str_tgt += '"'
else:
str_tgt += str_json[i]
str_tgt = str_tgt.replace(': None,', ': null,').replace(': False,', ': false,').replace(': True,', ': true,')
if isinstance(d, list):
self.data_json = list()
self.__build_json_data(self.data_json, self.__parse_json_objects(str_tgt), list)
elif isinstance(d, dict):
self.data_json = dict()
self.__build_json_data(self.data_json, self.__parse_json_objects(str_tgt), dict)
# Return a deep copy dump JSON object
def dumpDict(self):
print(u'[INFO] Return a dump object.')
return self.__deep_copy(self.data_json)
# Update the JSON data in dictionary
def update(self, d):
try:
self.data_json.update(d)
except ValueError:
print(u'[ERROR] Value error, please check!')
exit(1)
except:
print(u'[ERROR] Program exception!')
exit(1)
class JsonError(Exception):
def __init__(self, msg):
Exception.__init__(self, u'%s' % msg)
class JsonFormatError(JsonError):
def __init__(self, msg):
JsonError.__init__(self, u'[ERROR] %s' % msg)
class JsonValueError(JsonError):
def __init__(self, msg, var):
JsonError.__init__(self, u'[ERROR] %s >>> %s' % (msg, var))
class JsonInvalidKeywordError(JsonError):
def __init__(self, msg, kw):
JsonError.__init__(self, u'[ERROR] %s >>> %s' % (msg, kw))
Contents