Skip to content

Commit d02a760

Browse files
authored
Merge pull request #25 from debuggerx01/dev
merge dev to master
2 parents cb0b3c5 + b2e8167 commit d02a760

File tree

7 files changed

+170
-18
lines changed

7 files changed

+170
-18
lines changed

Test/IgnoreMapResp.dart

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import 'dart:convert' show json;
2+
3+
class IgnoreMapResp {
4+
5+
Data data;
6+
7+
IgnoreMapResp.fromParams({this.data});
8+
9+
factory IgnoreMapResp(jsonStr) => jsonStr == null ? null : jsonStr is String ? new IgnoreMapResp.fromJson(json.decode(jsonStr)) : new IgnoreMapResp.fromJson(jsonStr);
10+
11+
IgnoreMapResp.fromJson(jsonRes) {
12+
data = jsonRes['data'] == null ? null : new Data.fromJson(jsonRes['data']);
13+
}
14+
15+
@override
16+
String toString() {
17+
return '{"data": $data}';
18+
}
19+
}
20+
21+
class Data {
22+
23+
int wc;
24+
String author;
25+
String content;
26+
String digest;
27+
String title;
28+
Map<String, dynamic> date;
29+
Extra extra;
30+
31+
Data.fromParams({this.wc, this.author, this.content, this.digest, this.title, this.date, this.extra});
32+
33+
Data.fromJson(jsonRes) {
34+
wc = jsonRes['wc'];
35+
author = jsonRes['author'];
36+
content = jsonRes['content'];
37+
digest = jsonRes['digest'];
38+
title = jsonRes['title'];
39+
date = jsonRes['date'];
40+
extra = jsonRes['extra'] == null ? null : new Extra.fromJson(jsonRes['extra']);
41+
}
42+
43+
@override
44+
String toString() {
45+
return '{"wc": $wc,"author": ${author != null?'${json.encode(author)}':'null'},"content": ${content != null?'${json.encode(content)}':'null'},"digest": ${digest != null?'${json.encode(digest)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"date": ${date != null?'${json.encode(date)}':'null'},"extra": $extra}';
46+
}
47+
}
48+
49+
class Extra {
50+
51+
int a;
52+
int b;
53+
int c;
54+
55+
Extra.fromParams({this.a, this.b, this.c});
56+
57+
Extra.fromJson(jsonRes) {
58+
a = jsonRes['a'];
59+
b = jsonRes['b'];
60+
c = jsonRes['c'];
61+
}
62+
63+
@override
64+
String toString() {
65+
return '{"a": $a,"b": $b,"c": $c}';
66+
}
67+
}
68+

Test/IgnoreMapTest.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"data": {
3+
"author": "顾湘",
4+
"content": "content",
5+
"date": {
6+
"curr": "20180216",
7+
"next": "20180217",
8+
"prev": "20180215"
9+
},
10+
"extra":{
11+
"a": 1,
12+
"b": 2,
13+
"c": 3
14+
},
15+
"digest": "digest",
16+
"title": "新年的求婚者",
17+
"wc": 845
18+
}
19+
}

Test/test.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'EmptyResp.dart';
66
import 'RegionResp.dart';
77
import 'WanResp.dart';
88
import 'ListsResp.dart';
9+
import 'IgnoreMapResp.dart';
910

1011
void main() {
1112

@@ -201,12 +202,38 @@ void main() {
201202
expect(jsonRes, json.decode(resp.toString()));
202203
});
203204

205+
test('test ignore map', () {
206+
207+
String str = readFromFile('IgnoreMap');
208+
IgnoreMapResp resp = new IgnoreMapResp(str);
209+
var jsonRes = json.decode(str);
210+
211+
/// 测试传入String和json进行解析的结果是否相同
212+
expect(resp.toString(), new IgnoreMapResp(jsonRes).toString());
213+
214+
/// 逐个字段检查是否与json.decode()的结果相同
215+
expect(resp.data.wc, jsonRes['data']['wc']);
216+
expect(resp.data.author, jsonRes['data']['author']);
217+
expect(resp.data.content, jsonRes['data']['content']);
218+
expect(resp.data.digest, jsonRes['data']['digest']);
219+
expect(resp.data.title, jsonRes['data']['title']);
220+
expect(resp.data.extra.a, jsonRes['data']['extra']['a']);
221+
expect(resp.data.extra.b, jsonRes['data']['extra']['b']);
222+
expect(resp.data.extra.c, jsonRes['data']['extra']['c']);
223+
expect(resp.data.date, jsonRes['data']['date']);
224+
225+
/// 检查bean对象toString还原成json字符串后再交给json解析的结果是否与原始字符串相同
226+
expect(jsonRes, json.decode(resp.toString()));
227+
});
228+
204229

205230
}
206231

207232
String readFromFile(String name) {
208233
String str = new File('${name}Test.json').readAsStringSync();
209234
int index1 = str.indexOf('{');
210235
int index2 = str.indexOf('[');
236+
index1 = index1 == -1 ? 0: index1;
237+
index2 = index2 == -1 ? 0: index2;
211238
return str.substring(min(index1, index2));
212239
}

check_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from PyQt5.QtWidgets import QMessageBox
1717
from tools import msg_box_ui
1818

19-
code = 0.6
19+
code = 0.7
2020
ignore_code = 0.0
2121

2222
check_last_version_thread = None

formatter.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding:utf-8 -*-
3-
# @Filename : formater.py
3+
# @Filename : formatter.py
44
# @Date : 18-1-26 下午5:48
55
# @Author : DebuggerX
66
from functools import partial
@@ -13,7 +13,7 @@
1313
import pyperclip
1414

1515
# 定义显示的json格式化字符串的缩进量为4个空格
16-
indent = ' '
16+
indent = ' ' * 4
1717

1818
# 临时存储
1919
last_list_com_box = None
@@ -54,7 +54,14 @@ def analyse_json_obj(json_obj, level=0, res=None, json_key=None):
5454
else:
5555
res.append('%s<%s> : <[list]>9' % (indent * level, json_key))
5656
if len(json_obj) > 0:
57-
analyse_json_obj(json_obj[0], level + 1, res)
57+
json_obj_temp = json_obj[0] if json_obj[0] is not None else {}
58+
if len(list(filter(lambda item: type(item) is dict or item is None, json_obj))) == len(json_obj):
59+
for i in range(1, len(json_obj)):
60+
for k in json_obj[i]:
61+
if json_obj_temp is None or (k not in json_obj_temp or json_obj_temp[k] is None):
62+
json_obj_temp[k] = json_obj[i][k]
63+
json_obj_temp = None if json_obj_temp is {} else json_obj_temp
64+
analyse_json_obj(json_obj_temp, level + 1, res)
5865

5966
else:
6067
# 针对基本数据类型,在插入的键值对数据后再加入类型序号标志位
@@ -110,6 +117,7 @@ def get_type_combobox(need_connect, line):
110117

111118
com_box.setCurrentIndex(obj_type)
112119
elif obj_type == 8:
120+
com_box.addItem('Map<String, dynamic>')
113121
com_box.setCurrentText('')
114122
elif obj_type == 9:
115123
com_box.setCurrentText('List<>')
@@ -131,7 +139,8 @@ def update_list(json_str):
131139
json_obj = json.loads(json_str)
132140
# 传入json对象,返回所需要的格式化协议数据数组
133141
res = analyse_json_obj(json_obj)
134-
142+
global last_list_com_box
143+
last_list_com_box = None
135144
ui.tv_fields.setRowCount(len(res))
136145

137146
pre_type_combobox = None
@@ -206,11 +215,32 @@ def generate_bean():
206215
ui.te_json.setText(res)
207216

208217

218+
def str_to_camel_case(text):
219+
try:
220+
arr = filter(None, text.split('_'))
221+
res = ''
222+
for i in arr:
223+
res = res + i[0].upper() + i[1:]
224+
return res[0].lower() + res[1:]
225+
except IndexError:
226+
return text
227+
228+
229+
def convert_names_to_camel_case(index):
230+
if ui.tv_fields.horizontalHeaderItem(index).text() == 'Name(click to camelCase)':
231+
for i in range(ui.tv_fields.rowCount()):
232+
name_cell = ui.tv_fields.cellWidget(i, 2)
233+
if type(name_cell) is QtWidgets.QTextEdit:
234+
assert isinstance(name_cell, QtWidgets.QTextEdit)
235+
name_cell.setText(str_to_camel_case(name_cell.toPlainText()))
236+
237+
209238
def init_event():
210239
# 绑定json解析按钮事件
211240
ui.btn_format.clicked.connect(json_format)
212241
ui.btn_generate.clicked.connect(generate_bean)
213242
ui.btn_copy.clicked.connect(copy_left_text)
243+
ui.tv_fields.horizontalHeader().sectionClicked.connect(convert_names_to_camel_case)
214244

215245

216246
def copy_left_text():
@@ -222,7 +252,7 @@ def copy_left_text():
222252
# 设置表格基础样式
223253
def init_table():
224254
# 设置表头,表头文字居中
225-
ui.tv_fields.setHorizontalHeaderLabels(['Fields', 'Types', 'Name'])
255+
ui.tv_fields.setHorizontalHeaderLabels(['Fields', 'Types', 'Name(click to camelCase)'])
226256
ui.tv_fields.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignHCenter)
227257
# 表头自动平分宽度
228258
ui.tv_fields.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
@@ -253,5 +283,5 @@ def custom_ui():
253283
custom_ui()
254284
widget.show()
255285
code = check_version()
256-
widget.setWindowTitle(widget.windowTitle().replace('code',str(code)))
286+
widget.setWindowTitle(widget.windowTitle().replace('code', str(code)))
257287
sys.exit(app.exec_())

tools.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def jformat(inp):
3232

3333

3434
def check_level_type(t):
35+
if t == 'Map<String, dynamic>':
36+
# 不用处理的Map类型
37+
return 0
3538
if t in ('int', 'double', 'bool', 'Object'):
3639
# 普通数据类型
3740
return 1
@@ -64,10 +67,10 @@ def list_code_loop(code, count, total, n, ct):
6467

6568

6669
# 向代码模板中插入变量
67-
def build_list_construction(t, n):
70+
def build_list_construction(t, f, n):
6871
class_type = t.replace('List<', '').replace('>', '')
6972

70-
list_loop = 'jsonRes[\'%s\'] == null ? null : [];\n' % n
73+
list_loop = 'jsonRes[\'%s\'] == null ? null : [];\n' % f
7174
assert isinstance(t, str)
7275

7376
code = ''
@@ -83,7 +86,7 @@ def build_list_construction(t, n):
8386
else:
8487
code = code.replace('%s' % ('Child' * total), '%s' % ('Item' * total))
8588
code = code[code.find(';') + 1:]
86-
code = code.replace('%s){' % n, 'jsonRes[\'%s\']){' % n).replace('${loop}\n', '')
89+
code = code.replace('%s){' % n, 'jsonRes[\'%s\']){' % n).replace('${loop}\n', '').replace('jsonRes[\'%s\']){' % n, 'jsonRes[\'%s\']){' % f)
8790

8891
return list_loop + code
8992

@@ -109,11 +112,10 @@ def add_param_to_code(code, param):
109112
ps = code.find('${toString}')
110113
code = code[:ps] + to_string + code[ps:]
111114

112-
# 字符串类型处理,只需要修改toString中的输出方式
113-
114115
t_code = check_level_type(t)
115116

116-
if t_code == 2:
117+
# 字符串类型和Map类型处理,只需要修改toString中的输出方式
118+
if t_code in [0, 2]:
117119
code = code.replace(': $%s' % n, ': ${%s != null?\'${json.encode(%s)}\':\'null\'}' % (n, n))
118120

119121
# dict类型处理,只需要修改construction中的输出方式
@@ -122,7 +124,7 @@ def add_param_to_code(code, param):
122124

123125
# list类型处理,只需要修改construction中的输出方式
124126
elif t_code == 3:
125-
list_loop = build_list_construction(t, n)
127+
list_loop = build_list_construction(t, f, n)
126128

127129
code = code.replace('jsonRes[\'%s\'];' % f, list_loop)
128130

@@ -227,16 +229,22 @@ def check_and_generate_code(bean):
227229
work_bean = []
228230
global msg_box_ui
229231
msg_box_ui = bean[0][1]
230-
232+
ignore_level = None
231233
for f, t, n in bean:
232234
field_text = f.text()
233235

234236
level = field_text.find('※') // 4
237+
if ignore_level is not None and level > ignore_level:
238+
continue
239+
ignore_level = None
240+
235241
field_text = field_text[field_text.find("》") + 1: field_text.find(":") - 1] if ":" in field_text else ''
236242
type_text = t.currentText() if type(t) is QComboBox else t.toPlainText()
237243
name_text = n.text() if type(n) is QLabel else n.toPlainText()
244+
if type_text == 'Map<String, dynamic>':
245+
ignore_level = level
238246

239-
if type_text.strip() != '':
247+
if type_text.strip() != '' or ignore_level is not None:
240248
work_bean.append([level, field_text, type_text, name_text])
241249
else:
242250
QMessageBox().information(msg_box_ui, "警告", "字段类型未设置", QMessageBox.Ok)

version

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"code": 0.6,
3-
"desc": "1.修复json中字段不存在或者为null时可能导致的bean对象创建错误,也就是各字段处理时加入了null判断\n2.放弃对于普通数据类型数组的生成代码优化\n3.修复List嵌套泛型时由于错误的优化逻辑导致的异常代码\n4.优化清理无用空行"
2+
"code": 0.7,
3+
"desc": "1.可以通过下拉框将对象类型设置为Map<String, dynamic>来避免该对象字段的解析,参考issue #13\n2.点击Name栏使字段转为驼峰 & 解析List的时候读取多个元素,参考issue #17\n3.修复闪退崩溃issue #23"
44
}

0 commit comments

Comments
 (0)