3
3
# @Filename : formater.py
4
4
# @Date : 18-1-26 下午5:48
5
5
# @Author : DebuggerX
6
+ from functools import partial
6
7
7
8
from mainwindow import *
8
9
import json
9
10
11
+ # 定义显示的json格式化字符串的缩进量为4个空格
12
+ indent = ' '
10
13
14
+ # 临时存储
15
+ last_list_com_box = None
16
+
17
+
18
+ # 验证json字符串是否合法
11
19
def is_json (myjson ):
12
20
try :
13
21
json .loads (myjson )
@@ -16,25 +24,189 @@ def is_json(myjson):
16
24
return True
17
25
18
26
27
+ # 传入未格式化的单行json字符串,返回指定缩进的多行json字符串
19
28
def jformat (inp ):
20
29
obj = json .loads (inp )
21
30
outp = json .dumps (obj , skipkeys = False , ensure_ascii = False , check_circular = True , allow_nan = True , cls = None , indent = ' ' , separators = None ,
22
31
default = None , sort_keys = True )
23
32
return outp
24
33
25
34
35
+ def analyse_json_obj (json_obj , level = 0 , res = None , json_key = None ):
36
+ if res is None :
37
+ res = []
38
+
39
+ # 对字典对象的属性按照基本数据类型->list类型->dict类型的次序排序
40
+ if isinstance (json_obj , dict ):
41
+ json_obj = sorted (
42
+ json_obj .items (), key = lambda x :
43
+ (
44
+ isinstance (x [1 ], dict ),
45
+ isinstance (x [1 ], list ),
46
+ isinstance (x [1 ], str ),
47
+ isinstance (x [1 ], bool ),
48
+ isinstance (x [1 ], float ),
49
+ isinstance (x [1 ], int ),
50
+ x [0 ]
51
+ )
52
+ )
53
+
54
+ # 插入父层级数据为dict类型,类型序号为8,层级深度+1,遍历解析所有子属性
55
+ if json_key is None :
56
+ res .append ('%s<[dict]>8' % (indent * level ))
57
+ else :
58
+ res .append ('%s<%s> : <[dict]>8' % (indent * level , json_key ))
59
+ level += 1
60
+ for key , value in json_obj :
61
+ analyse_json_obj (value , level , res , key )
62
+
63
+ elif isinstance (json_obj , list ):
64
+ # 插入父层级数据为list类型,类型序号为9,层级深度+1,并取其第一个元素继续解析
65
+ if json_key is None :
66
+ res .append ('%s<[list]>9' % (indent * level ))
67
+ else :
68
+ res .append ('%s <%s> : <[list]>9' % (indent * level , json_key ))
69
+ if len (json_obj ) > 0 :
70
+ analyse_json_obj (json_obj [0 ], level + 1 , res )
71
+
72
+ else :
73
+ # 针对基本数据类型,在插入的键值对数据后再加入类型序号标志位
74
+ obj_type = type (json_obj )
75
+ if obj_type is int :
76
+ obj_type = 1
77
+ elif obj_type is float :
78
+ obj_type = 2
79
+ elif obj_type is bool :
80
+ obj_type = 3
81
+ elif obj_type is str :
82
+ obj_type = 4
83
+ else :
84
+ obj_type = 0
85
+ res .append ('%s<%s> : <%s>%d' % (indent * level , json_key , json_obj , obj_type ))
86
+
87
+ return res
88
+
89
+
90
+ def change_text (com_box , current_text ):
91
+ com_box .setCurrentText ('List<%s>' % current_text )
92
+
93
+
94
+ # 生成字段类型下拉框
95
+ def get_type_combobox (line ):
96
+ com_box = QtWidgets .QComboBox ()
97
+ com_box .setEditable (True )
98
+ obj_type = int (line [- 1 ]) if line [- 1 ].isdigit () else 0
99
+
100
+ if last_list_com_box is not None :
101
+ com_box .currentTextChanged .connect (partial (change_text , last_list_com_box ))
102
+ last_list_com_box = None
103
+
104
+ # 根据字段数据的最后一位数字标记指定下拉框默认类型
105
+ if obj_type < 8 :
106
+ com_box .addItem ('Object' )
107
+ com_box .addItem ('int' )
108
+ com_box .addItem ('double' )
109
+ com_box .addItem ('bool' )
110
+ com_box .addItem ('String' )
111
+
112
+ com_box .setCurrentIndex (obj_type )
113
+ elif obj_type == 8 :
114
+ com_box .setCurrentText ('' )
115
+ elif obj_type == 9 :
116
+ com_box .setCurrentText ('List<>' )
117
+ # 将该list字段的编辑框临时保存,用于与下一个字段的类型绑定
118
+ global last_list_com_box
119
+ last_list_com_box = com_box
120
+
121
+ return com_box
122
+
123
+
124
+ def get_name_text_edit (line ):
125
+ te = QtWidgets .QTextEdit (line [line .find ('<' ) + 1 :line .find ('>' )])
126
+
127
+ return te
128
+
129
+
130
+ def update_list (json_str ):
131
+ json_obj = json .loads (json_str )
132
+ # 传入json对象,返回所需要的格式化协议数据数组
133
+ res = analyse_json_obj (json_obj )
134
+
135
+ ui .tv_fields .setRowCount (len (res ))
136
+
137
+ for i in range (len (res )):
138
+ line = res [i ]
139
+ assert isinstance (line , str )
140
+ index = line .find ('<' )
141
+
142
+ ui .tv_fields .setCellWidget (i , 1 , get_type_combobox (line ))
143
+ if line .strip () == '<[dict]>8' :
144
+ label = QtWidgets .QLabel ("" )
145
+ label .setStyleSheet ("background-color: rgb(200,200,200);" )
146
+ ui .tv_fields .setCellWidget (i , 2 , label )
147
+ else :
148
+ ui .tv_fields .setCellWidget (i , 2 , get_name_text_edit (line ))
149
+
150
+ if index == 0 :
151
+ field = line .replace ('<' , '' ).replace ('>' , '' )
152
+ else :
153
+ field = ("%s※==》%s" % (' ' * (index - 4 ), line [index :])).replace ('<' , '' ).replace ('>' , '' )
154
+
155
+ label = QtWidgets .QLabel ()
156
+ label .setText (field [0 :60 ] + '...' if len (field ) > 60 else field [0 :- 1 ])
157
+ label .setToolTip (field [0 :- 1 ])
158
+
159
+ ui .tv_fields .setCellWidget (i , 0 , label )
160
+
161
+ ui .tv_fields .resizeColumnToContents (0 )
162
+
163
+
26
164
def json_format ():
165
+ # 从文本编辑框获取json字符串
27
166
json_str = ui .te_json .toPlainText ()
28
167
if is_json (json_str ):
168
+ # 将格式化后的json字符串覆盖到文本编辑框中
29
169
ui .te_json .setText (jformat (json_str .replace ('\n ' , '' )))
170
+
171
+ # 根据json更新表格条目
172
+ update_list (json_str )
173
+
30
174
else :
31
175
msg = QtWidgets .QMessageBox ()
32
176
msg .information (ui .te_json , "警告" , "JSON不合法" , QtWidgets .QMessageBox .Ok )
33
177
34
178
179
+ def generate_bean ():
180
+ ui .te_json .setText ("OK" )
181
+
182
+
183
+ def init_event ():
184
+ # 绑定json解析按钮事件
185
+ ui .btn_format .clicked .connect (json_format )
186
+ ui .btn_generate .clicked .connect (generate_bean )
187
+
188
+
189
+ # 设置表格基础样式
190
+ def init_table ():
191
+ # 设置表头,表头文字居中
192
+ ui .tv_fields .setHorizontalHeaderLabels (['Fields' , 'Types' , 'Name' ])
193
+ ui .tv_fields .horizontalHeader ().setDefaultAlignment (QtCore .Qt .AlignHCenter )
194
+ # 表头自动平分宽度
195
+ ui .tv_fields .horizontalHeader ().setSectionResizeMode (QtWidgets .QHeaderView .Stretch )
196
+ # 设置第一列为固定宽度,不参与平分
197
+ ui .tv_fields .horizontalHeader ().setSectionResizeMode (0 , QtWidgets .QHeaderView .Fixed )
198
+ ui .tv_fields .resizeColumnToContents (0 )
199
+ # 隐藏左侧垂直表头
200
+ ui .tv_fields .verticalHeader ().setVisible (False )
201
+
202
+
203
+ def init_view ():
204
+ init_table ()
205
+
206
+
35
207
def customUI ():
36
- ui . te_json . format = json_format
37
- ui . btn_format . clicked . connect ( ui . te_json . format )
208
+ init_view ()
209
+ init_event ( )
38
210
39
211
40
212
if __name__ == "__main__" :
0 commit comments