class JsonParser:
def __init__(self, s):
self.s = s
self.idx = 0
def match(self, t):
if self.curr_char() == t:
self.idx += 1
else:
print(self.curr_char())
print('match ERROR', t)
exit()
def curr_char(self):
while self.s[self.idx].isspace():
self.idx += 1
return self.s[self.idx]
def common_parse(self):
"""
递归下降分析: str-->json
"""
if self.curr_char() == '[':
return self.parse_list()
elif self.curr_char() == '{':
return self.parse_dict()
else:
return self.parse_basic()
def parse_dict(self):
self.match('{')
rtv = {}
while True:
key = self.parse_basic()
self.match(':')
value = self.common_parse()
rtv[key] = value
if self.curr_char() != ',':
break
self.match(',')
self.match('}')
return rtv
def parse_list(self):
self.match('[')
rtv = []
while True:
item = self.common_parse()
rtv.append(item)
if self.curr_char() != ',':
break
self.match(',')
self.match(']')
return rtv
def parse_basic(self):
"""
int, none, bool, str
"""
tmp = self.curr_char()
if tmp.isdigit():
self.idx += 1
while self.curr_char().isdigit():
tmp += self.curr_char()
self.idx += 1
return int(tmp)
elif tmp == 'n':
for c in 'null':
self.match(c)
return None
elif tmp == 't':
for c in 'true':
self.match(c)
return True
elif tmp == 'f':
for c in 'false':
self.match(c)
return False
elif tmp == '"':
self.match('"')
tmp = ''
while self.curr_char() != '"':
tmp += self.curr_char()
self.idx += 1
self.match('"')
return tmp
class JsonDump:
@classmethod
def dump(cls, o):
return ''.join([s for s in cls.common_dump(o)])
@classmethod
def common_dump(cls, o):
"""
深度优先遍历: json-->str
"""
if isinstance(o, list):
yield from cls.dump_list(o)
elif isinstance(o, dict):
yield from cls.dump_dict(o)
else:
yield from cls.dump_basic(o)
@classmethod
def dump_list(cls, o):
idx, length = 0, len(o)
yield '['
for item in o:
yield from cls.common_dump(item)
idx += 1
if idx < length:
yield ','
yield ']'
@classmethod
def dump_dict(cls, o):
idx, length = 0, len(o)
yield '{'
for k, v in o.items():
yield from cls.common_dump(k)
yield ':'
yield from cls.common_dump(v)
idx += 1
if idx < length:
yield ','
yield '}'
@classmethod
def dump_basic(cls, o):
if o == True:
yield 'true'
elif o == False:
yield 'false'
elif o == None:
yield 'null'
elif isinstance(o, str):
yield '"'
yield o
yield '"'
elif isinstance(o, int):
yield str(o)
if __name__ == '__main__':
s = '{"hello": "world", "game": "war", "LIST": [1, 2, 3, {"Bang": false}]}'
s2 = '{"paths":[{"path":"/:firewall:13","mac":false,"mac_users":[]}],"data":{"action":"add_rule","protocol":"TCP","cidr":"116.116.116.12/32","port_range":"80/8080","policy":"Accept","desc":"test"}}'
jp = JsonParser(s2)
print(s2)
from pprint import pprint
pprint(jp.common_parse())
o = {'hello': 'world', 'game': 'war', 'LIST': [1, 2, 3, {'Bang': False}]}
print(o)
print(JsonDump.dump(o))
运行效果:
E:\workspace\sept>python json_parse.py
{"paths":[{"path":"/:firewall:13","mac":false,"mac_users":[]}],"data":{"action":"add_rule","protocol":"TCP","cidr":"116.116.116.12/32","por
t_range":"80/8080","policy":"Accept","desc":"test"}}
{'data': {'action': 'add_rule',
'cidr': '116.116.116.12/32',
'desc': 'test',
'policy': 'Accept',
'port_range': '80/8080',
'protocol': 'TCP'},
'paths': [{'mac': False, 'mac_users': [None], 'path': '/:firewall:13'}]}
{'hello': 'world', 'game': 'war', 'LIST': [1, 2, 3, {'Bang': False}]}
{"hello":"world","game":"war","LIST":[true,2,3,{"Bang":false}]}