├── .gitignore ├── img └── ui.png ├── bin ├── jsonView.exe ├── jsonview.jar └── jsonview.vbs ├── lib ├── org-openide-awt.jar ├── rsyntaxtextarea.jar ├── org-openide-util.jar ├── org-openide-windows.jar ├── org-netbeans-swing-tabcontrol.jar └── install.bat ├── src └── main │ ├── resources │ ├── json.gif │ └── json.ico │ └── java │ └── cy │ └── jsonview │ ├── resources │ ├── a.gif │ ├── k.gif │ ├── n.gif │ ├── o.gif │ ├── v.gif │ ├── about.png │ ├── json.ico │ ├── json.png │ ├── splash.png │ ├── bookmark.png │ └── readme │ ├── listener │ ├── QuitActionListener.java │ ├── TabDataModelComplexListDataListener.java │ ├── FileSaveActionListener.java │ ├── FileOpenActionListener.java │ ├── TreeMouseListener.java │ ├── TreeNodeMenuItemActionListener.java │ └── FindActionListener.java │ └── code │ ├── AboutDialog.java │ ├── Log.java │ ├── SelCompUtil.java │ ├── Kit.java │ └── MainApp.java ├── README.md ├── pom.xml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | target/ 3 | .idea 4 | -------------------------------------------------------------------------------- /img/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/img/ui.png -------------------------------------------------------------------------------- /bin/jsonView.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/bin/jsonView.exe -------------------------------------------------------------------------------- /bin/jsonview.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/bin/jsonview.jar -------------------------------------------------------------------------------- /lib/org-openide-awt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/lib/org-openide-awt.jar -------------------------------------------------------------------------------- /lib/rsyntaxtextarea.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/lib/rsyntaxtextarea.jar -------------------------------------------------------------------------------- /lib/org-openide-util.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/lib/org-openide-util.jar -------------------------------------------------------------------------------- /lib/org-openide-windows.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/lib/org-openide-windows.jar -------------------------------------------------------------------------------- /src/main/resources/json.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/resources/json.gif -------------------------------------------------------------------------------- /src/main/resources/json.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/resources/json.ico -------------------------------------------------------------------------------- /bin/jsonview.vbs: -------------------------------------------------------------------------------- 1 | Set ws = CreateObject("Wscript.Shell") 2 | ws.run "cmd /c java -jar jsonview.jar > log.txt",vbhide -------------------------------------------------------------------------------- /lib/org-netbeans-swing-tabcontrol.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/lib/org-netbeans-swing-tabcontrol.jar -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/a.gif -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/k.gif -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/n.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/n.gif -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/o.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/o.gif -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/v.gif -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/about.png -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/json.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/json.ico -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/json.png -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/splash.png -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/bookmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hao117/JsonView/HEAD/src/main/java/cy/jsonview/resources/bookmark.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JsonView 2 | 3 | #### 介绍 4 | 一个json格式化查看工具 5 | 6 | 可执行文件在 /JsonView/bin目录 7 | 8 | 联系方式:邮箱beetle082@163.com,qq:275951533 9 | 10 | **源码地址**
11 | https://gitee.com/beetle082/JsonView
12 | https://github.com/hao117/JsonView
13 | ![](./img/ui.png) -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/QuitActionListener.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.listener; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | 6 | /** 7 | * 8 | * @author cangyan 9 | */ 10 | public class QuitActionListener implements ActionListener{ 11 | 12 | @Override 13 | public void actionPerformed(ActionEvent e) { 14 | System.exit(0); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lib/install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | call mvn install:install-file -Dfile=org-netbeans-swing-tabcontrol.jar -DgroupId=org.netbeans -DartifactId=org-netbeans-swing-tabcontrol -Dversion=200804211638 -Dpackaging=jar 3 | call mvn install:install-file -Dfile=org-openide-awt.jar -DgroupId=org.netbeans -DartifactId=org-openide-awt -Dversion=200804211638 -Dpackaging=jar 4 | call mvn install:install-file -Dfile=org-openide-util.jar -DgroupId=org.netbeans -DartifactId=org-openide-util -Dversion=200804211638 -Dpackaging=jar 5 | call mvn install:install-file -Dfile=org-openide-windows.jar -DgroupId=org.netbeans -DartifactId=org-openide-windows -Dversion=200804211638 -Dpackaging=jar 6 | call mvn install:install-file -Dfile=rsyntaxtextarea.jar -DgroupId=com.fifesoft -DartifactId=rsyntaxtextarea -Dversion=2.6.1 -Dpackaging=jar 7 | pause -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/code/AboutDialog.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.code; 2 | 3 | import javax.swing.BoxLayout; 4 | import javax.swing.JDialog; 5 | import javax.swing.JFrame; 6 | import javax.swing.JLabel; 7 | 8 | /** 9 | * 关于. 10 | * @author cangyan 11 | */ 12 | public class AboutDialog { 13 | 14 | public static void show(JFrame frame){ 15 | JDialog dlg = new JDialog(frame); 16 | dlg.setTitle("关于"); 17 | dlg.setModal(false); 18 | dlg.setSize(260,160); 19 | dlg.setResizable(false); 20 | dlg.setLocationRelativeTo(frame); 21 | 22 | java.awt.Container pane = dlg.getContentPane(); 23 | BoxLayout layout = new BoxLayout(pane, BoxLayout.Y_AXIS); 24 | pane.setLayout(layout); 25 | pane.add(new JLabel(" ")); 26 | pane.add(new JLabel(" CyJsonView 2.3.3")); 27 | pane.add(new JLabel(" ")); 28 | pane.add(new JLabel(" 作者:藏言")); 29 | pane.add(new JLabel(" ")); 30 | pane.add(new JLabel(" 邮箱:beetle082@163.com")); 31 | dlg.setVisible(true); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/code/Log.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package cy.jsonview.code; 8 | 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.io.PrintWriter; 12 | import java.io.StringWriter; 13 | import org.openide.util.Exceptions; 14 | 15 | /** 16 | * 17 | * @author cangyan 18 | */ 19 | public class Log { 20 | public static void write(String s){ 21 | try { 22 | FileWriter fileWriter=new FileWriter("log.txt",true); 23 | fileWriter.write(s+"\r\n"); 24 | fileWriter.flush(); 25 | fileWriter.close(); 26 | } catch (IOException ex) { 27 | Exceptions.printStackTrace(ex); 28 | } 29 | } 30 | 31 | public static void write(Exception e){ 32 | try { 33 | StringWriter sw = new StringWriter(); 34 | PrintWriter pw = new PrintWriter(sw); 35 | e.printStackTrace(pw); 36 | write("异常:"+sw.toString()); 37 | }catch (Exception ex) { 38 | write("write Exception异常"); 39 | Exceptions.printStackTrace(ex); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/resources/readme: -------------------------------------------------------------------------------- 1 | 0.1 2 | json格式化 3 | 窗口布局设置 4 | 5 | 0.2 6 | 代码优化 7 | 8 | 0.3 9 | 代码优化 10 | 新增工具条 11 | 新增工具条按钮[json格式化] 12 | 新增工具条按钮[标题修改] 13 | 14 | 0.4 15 | 代码优化 16 | 新增工具条按钮[清空] 17 | 新增工具条按钮[粘帖] 18 | 19 | 0.5 20 | 代码优化 21 | 新增工具条按钮[节点查找] 22 | 23 | 0.6 24 | 界面优化 25 | 新增树右键菜单[复制Key][复制Value] 26 | 27 | 0.7 28 | 新增[文件]->[打开文件] 29 | 新增[文件]->[保存文件] 30 | 新增工具条按钮[清除换行符] 31 | 新增工具条按钮[清除斜杠] 32 | 新增工具条按钮[文本查找] 33 | 34 | 0.8 35 | 界面调整 36 | 节点查找优化 37 | 文本查找优化 38 | 39 | 0.9 40 | 新增树右键菜单[复制keyValue] 41 | 新增文本框右键菜单[复制] 42 | 新增文本框右键菜单[粘帖] 43 | 新增文本框右键菜单[全选] 44 | 新增文本框右键菜单[恢复] 45 | 新增文本框右键菜单[撤销] 46 | 47 | 1.0 48 | 优化[保存文件][打开文件]菜单响应速度 49 | json树生成,数组处理bug修改 50 | 修改树右键菜单部分英文为中文 51 | 新增格式化JSON异常提示 52 | 新增[帮助]->[编码转换] 53 | 新增树右键菜单[复制路径] 54 | 新增树右键菜单[复制同路径键值] 55 | 新增树右键菜单[复制节点内容] 56 | 新增树右键菜单[复制节点内容带格式] 57 | 58 | 1.1 59 | 新增启动画面 60 | 优化启动速度 61 | 更改文件打开和保存方式 62 | 63 | 1.2 64 | 内存优化 65 | 十六进制编码转换 66 | 67 | 1.3 68 | ... 69 | 70 | 2.0 71 | 新增标签 72 | 重构代码 73 | 74 | 2.1 75 | json文本折叠代码和着色 76 | 77 | 2.1.1 78 | 重构部分代码 79 | 增加[复制MAP式内容] 80 | 增加打开文件后自动格式化 81 | 增加用工具栏粘帖按钮进行粘帖后进行自动格式化 82 | 83 | 2.1.2 84 | 新增排序 85 | 86 | 2.1.3 87 | 格式化按钮加亮 88 | 修正null不显示 89 | 90 | 2.1.4 91 | 测试 92 | 93 | 2.1.5 94 | 更改使用fastjson,修改算法 95 | 96 | 2.2.0 97 | 增加MAP系列化字符串转换成JSON 98 | 增加XML字符转换成JSON 99 | 增加XML格式化 100 | 增加右键菜单[复制xml] 101 | 102 | 2.3 103 | 代码重构 104 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/TabDataModelComplexListDataListener.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.listener; 2 | 3 | import cy.jsonview.code.SelCompUtil; 4 | import java.util.Map; 5 | import javax.swing.JTree; 6 | import javax.swing.event.ListDataEvent; 7 | import org.netbeans.swing.tabcontrol.TabData; 8 | import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent; 9 | import org.netbeans.swing.tabcontrol.event.ComplexListDataListener; 10 | 11 | /** 12 | * @author cangyan 13 | */ 14 | public class TabDataModelComplexListDataListener implements ComplexListDataListener { 15 | private final Map jsonEleTreeMap; 16 | public TabDataModelComplexListDataListener(Map jsonEleTreeMap){ 17 | this.jsonEleTreeMap = jsonEleTreeMap; 18 | } 19 | @Override 20 | public void indicesAdded(ComplexListDataEvent clde) {} 21 | @Override 22 | public void indicesRemoved(ComplexListDataEvent clde) {} 23 | @Override 24 | public void indicesChanged(ComplexListDataEvent clde) {} 25 | @Override 26 | public void intervalAdded(ListDataEvent e) {} 27 | @Override 28 | public void intervalRemoved(ListDataEvent e) { 29 | ComplexListDataEvent ce = (ComplexListDataEvent)e; 30 | TabData[] tbArr = ce.getAffectedItems(); 31 | if(tbArr!=null && tbArr.length>0){ 32 | tbArr[0].getText(); 33 | JTree tree = getTree(tbArr[0]); 34 | if(tree!=null){ 35 | jsonEleTreeMap.remove(tree.hashCode()); 36 | System.out.println("Remove HashCode: "+ tree.hashCode() + ". Close Tab: " + tbArr[0].getText() + " !"); 37 | } 38 | } 39 | } 40 | @Override 41 | public void contentsChanged(ListDataEvent e) {} 42 | 43 | private JTree getTree(TabData tabData){ 44 | return SelCompUtil.getTree(tabData); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/FileSaveActionListener.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.listener; 2 | 3 | import cy.jsonview.code.SelCompUtil; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.OutputStreamWriter; 11 | import javax.swing.JFrame; 12 | import javax.swing.JTextArea; 13 | import org.apache.commons.lang.StringUtils; 14 | import org.netbeans.swing.tabcontrol.TabbedContainer; 15 | 16 | /** 17 | * 18 | * @author cangyan 19 | */ 20 | public class FileSaveActionListener implements ActionListener{ 21 | private final JFrame frame; 22 | private final TabbedContainer tabbedContainer; 23 | private final String dlgTitle; 24 | public FileSaveActionListener(JFrame frame,TabbedContainer tabbedContainer,String dlgTitle){ 25 | this.frame = frame; 26 | this.tabbedContainer = tabbedContainer; 27 | this.dlgTitle = dlgTitle; 28 | } 29 | 30 | 31 | @Override 32 | public void actionPerformed(ActionEvent e) { 33 | java.awt.FileDialog closeDlg = new java.awt.FileDialog(frame, dlgTitle, java.awt.FileDialog.SAVE); 34 | closeDlg.setVisible(true); 35 | File file = new File(closeDlg.getDirectory(),closeDlg.getFile()); 36 | if(StringUtils.isBlank(closeDlg.getDirectory())||StringUtils.isBlank(closeDlg.getFile())){ 37 | return; 38 | } 39 | BufferedWriter write= null; 40 | try { 41 | OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file),"GBK"); 42 | write = new BufferedWriter(osw); 43 | JTextArea textArea = SelCompUtil.getTextArea(tabbedContainer); 44 | String text = StringUtils.replace(textArea.getText(), "\n", "\r\n"); 45 | write.write(text, 0, text.length()); 46 | write.close(); 47 | } catch (IOException ex) { 48 | 49 | } finally { 50 | if (write != null) { 51 | try { 52 | write.close(); 53 | } catch (IOException e1) { 54 | } 55 | } 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/FileOpenActionListener.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.listener; 2 | 3 | import cy.jsonview.code.SelCompUtil; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.BufferedReader; 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import javax.swing.JFrame; 12 | import org.apache.commons.lang.StringUtils; 13 | import org.netbeans.swing.tabcontrol.TabbedContainer; 14 | 15 | /** 16 | * 17 | * @author cangyan 18 | */ 19 | public class FileOpenActionListener implements ActionListener{ 20 | private final JFrame frame; 21 | private final TabbedContainer tabbedContainer; 22 | private final String dlgTitle; 23 | public FileOpenActionListener(JFrame frame,TabbedContainer tabbedContainer,String dlgTitle){ 24 | this.frame = frame; 25 | this.tabbedContainer = tabbedContainer; 26 | this.dlgTitle = dlgTitle; 27 | } 28 | 29 | 30 | @Override 31 | public void actionPerformed(ActionEvent e) { 32 | java.awt.FileDialog openDlg = new java.awt.FileDialog(frame, dlgTitle, java.awt.FileDialog.LOAD); 33 | openDlg.setVisible(true); 34 | if(StringUtils.isBlank(openDlg.getDirectory())||StringUtils.isBlank(openDlg.getFile())){ 35 | return; 36 | } 37 | File file = new File(openDlg.getDirectory(),openDlg.getFile()); //fc.getSelectedFile(); 38 | BufferedReader reader = null; 39 | StringBuilder sb = new StringBuilder(); 40 | try { 41 | InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "GBK"); 42 | reader = new BufferedReader(isr); 43 | String temp; 44 | while ((temp = reader.readLine()) != null) { 45 | sb.append(temp); 46 | } 47 | reader.close(); 48 | } catch (IOException ex) { 49 | 50 | } finally { 51 | if (reader != null) { 52 | try { 53 | reader.close(); 54 | } catch (IOException ex) { 55 | } 56 | } 57 | } 58 | SelCompUtil.getTextArea(tabbedContainer).setText(sb.toString()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/code/SelCompUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package cy.jsonview.code; 8 | 9 | import javax.swing.JScrollPane; 10 | import javax.swing.JSplitPane; 11 | import javax.swing.JTable; 12 | import javax.swing.JTree; 13 | import javax.swing.JViewport; 14 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; 15 | import org.netbeans.swing.tabcontrol.TabData; 16 | import org.netbeans.swing.tabcontrol.TabDataModel; 17 | import org.netbeans.swing.tabcontrol.TabbedContainer; 18 | 19 | /** 20 | * 21 | * @author cangyan 22 | */ 23 | public class SelCompUtil { 24 | public static int getTabIndex(TabbedContainer tabbedContainer){ 25 | return tabbedContainer.getSelectionModel().getSelectedIndex(); 26 | } 27 | 28 | public TabDataModel getTabDataModel(TabbedContainer tabbedContainer){ 29 | return tabbedContainer.getModel(); 30 | } 31 | 32 | public static RSyntaxTextArea getTextArea(TabbedContainer tabbedContainer){ 33 | int selIndex = getTabIndex(tabbedContainer); 34 | TabDataModel tabDataModel = tabbedContainer.getModel(); 35 | if(selIndex >= 0){ 36 | TabData selTabData = tabDataModel.getTab(selIndex); 37 | JSplitPane selSplitPane = (JSplitPane)selTabData.getComponent(); 38 | JScrollPane sp = (JScrollPane)selSplitPane.getLeftComponent(); 39 | JViewport vp = (JViewport)sp.getComponent(0); 40 | RSyntaxTextArea ta = (RSyntaxTextArea)vp.getComponent(0); 41 | return ta; 42 | } 43 | return null; 44 | } 45 | 46 | 47 | public static JTree getTree(TabData tabData){ 48 | if(tabData==null){ 49 | return null; 50 | } 51 | JSplitPane selSplitPane = (JSplitPane)tabData.getComponent(); 52 | JScrollPane sp = (JScrollPane)selSplitPane.getRightComponent(); 53 | JViewport vp = (JViewport)sp.getComponent(0); 54 | JTree t = (JTree)vp.getComponent(0); 55 | return t; 56 | } 57 | public static JTree getTree(TabDataModel tabDataModel,int tabIndex){ 58 | if(tabIndex >= 0){ 59 | TabData selTabData = tabDataModel.getTab(tabIndex); 60 | return getTree(selTabData); 61 | } 62 | return null; 63 | } 64 | 65 | public static JTree getTree(TabbedContainer tabbedContainer){ 66 | return getTree(tabbedContainer.getModel(),getTabIndex(tabbedContainer)); 67 | } 68 | 69 | public static JTable getTable(int tabIndex,TabbedContainer tabbedContainer){ 70 | if(tabIndex >= 0){ 71 | TabData selTabData = tabbedContainer.getModel().getTab(tabIndex); 72 | JSplitPane selSplitPane = (JSplitPane)selTabData.getComponent(); 73 | JSplitPane rightSplitPane = (JSplitPane)selSplitPane.getRightComponent(); 74 | JScrollPane sp = (JScrollPane)rightSplitPane.getRightComponent(); 75 | JViewport vp = (JViewport)sp.getComponent(0); 76 | JTable t = (JTable)vp.getComponent(0); 77 | return t; 78 | } 79 | return null; 80 | } 81 | 82 | public static JTable getTable(TabbedContainer tabbedContainer){ 83 | return getTable(getTabIndex(tabbedContainer),tabbedContainer); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/TreeMouseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package cy.jsonview.listener; 8 | 9 | import java.awt.event.MouseEvent; 10 | import java.awt.event.MouseListener; 11 | import java.util.Map; 12 | import javax.swing.JMenuItem; 13 | import javax.swing.JPopupMenu; 14 | import javax.swing.JTree; 15 | import javax.swing.tree.DefaultMutableTreeNode; 16 | import javax.swing.tree.TreePath; 17 | 18 | /** 19 | * 20 | * @author cangyan 21 | */ 22 | public class TreeMouseListener implements MouseListener { 23 | private final JTree tree; 24 | private final Map jsonEleTreeMap; 25 | public TreeMouseListener(JTree tree,Map jsonEleTreeMap){ 26 | this.tree = tree; 27 | this.jsonEleTreeMap = jsonEleTreeMap; 28 | } 29 | 30 | @Override 31 | public void mouseClicked(MouseEvent e) {} 32 | 33 | @Override 34 | public void mousePressed(MouseEvent e) {} 35 | 36 | @Override 37 | public void mouseReleased(MouseEvent e) { 38 | TreePath path = tree.getPathForLocation(e.getX(), e.getY()); 39 | if (path == null) return; 40 | tree.setSelectionPath(path); 41 | DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 42 | if (e.isPopupTrigger()) { 43 | JPopupMenu popMenu = new JPopupMenu(); 44 | JMenuItem copyValue = new JMenuItem("复制 键值"); 45 | JMenuItem copyKey = new JMenuItem("复制 键名"); 46 | JMenuItem copyPath = new JMenuItem("复制 路径"); 47 | JMenuItem copyKeyValue = new JMenuItem("复制 键名键值"); 48 | JMenuItem copyNode = new JMenuItem("复制 节点内容"); 49 | JMenuItem copyPathAllVal = new JMenuItem("复制 同路径键值"); 50 | JMenuItem copySingleNodeString = new JMenuItem("复制 MAP式内容"); 51 | JMenuItem copyNodeFormat = new JMenuItem("复制 节点内容带格式"); 52 | 53 | popMenu.add(copyKey); 54 | popMenu.add(copyValue); 55 | popMenu.add(copyPath); 56 | popMenu.add(copyNode); 57 | popMenu.add(copyKeyValue); 58 | popMenu.add(copySingleNodeString); 59 | popMenu.add(copyPathAllVal); 60 | popMenu.add(copyNodeFormat); 61 | copyKey.addActionListener(new TreeNodeMenuItemActionListener(tree,1, selNode,jsonEleTreeMap)); 62 | copyValue.addActionListener(new TreeNodeMenuItemActionListener(tree,2, selNode,jsonEleTreeMap)); 63 | copyKeyValue.addActionListener(new TreeNodeMenuItemActionListener(tree,3, selNode,jsonEleTreeMap)); 64 | copyPath.addActionListener(new TreeNodeMenuItemActionListener(tree,4, path,jsonEleTreeMap)); 65 | copyPathAllVal.addActionListener(new TreeNodeMenuItemActionListener(tree,5,selNode,jsonEleTreeMap)); 66 | copyNode.addActionListener(new TreeNodeMenuItemActionListener(tree,6,path,jsonEleTreeMap)); 67 | copyNodeFormat.addActionListener(new TreeNodeMenuItemActionListener(tree,7,path,jsonEleTreeMap)); 68 | copySingleNodeString.addActionListener(new TreeNodeMenuItemActionListener(tree,8,selNode,jsonEleTreeMap)); 69 | popMenu.show(e.getComponent(), e.getX(), e.getY()); 70 | } 71 | } 72 | 73 | @Override 74 | public void mouseEntered(MouseEvent e) {} 75 | 76 | @Override 77 | public void mouseExited(MouseEvent e) {} 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/TreeNodeMenuItemActionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package cy.jsonview.listener; 8 | 9 | import com.alibaba.fastjson.JSON; 10 | import com.alibaba.fastjson.JSONObject; 11 | import com.alibaba.fastjson.serializer.SerializerFeature; 12 | import cy.jsonview.code.Kit; 13 | import cy.jsonview.code.MainApp; 14 | import java.awt.Toolkit; 15 | import java.awt.datatransfer.Clipboard; 16 | import java.awt.datatransfer.StringSelection; 17 | import java.awt.event.ActionEvent; 18 | import java.awt.event.ActionListener; 19 | import java.util.Map; 20 | import javax.swing.JTree; 21 | import javax.swing.tree.TreeNode; 22 | import javax.swing.tree.TreePath; 23 | import org.apache.commons.lang.StringUtils; 24 | 25 | /** 26 | * 27 | * @author cangyan 28 | */ 29 | public class TreeNodeMenuItemActionListener implements ActionListener{ 30 | private final int optType; 31 | private final Object obj; 32 | private final JTree tree; 33 | private final Map jsonEleTreeMap; 34 | /** 35 | * optType 1:key;2:value;3:key value 36 | * @param optType 37 | */ 38 | public TreeNodeMenuItemActionListener(JTree tree,int optType,Object obj,Map jsonEleTreeMap){ 39 | this.optType = optType; 40 | this.obj = obj; 41 | this.tree = tree; 42 | this.jsonEleTreeMap = jsonEleTreeMap; 43 | } 44 | /** 45 | * 复制节点路径. 46 | * @param treePath 47 | * @return 48 | */ 49 | public String copyTreeNodePath(TreePath treePath){ 50 | String str = ""; 51 | String s; 52 | int len = treePath.getPathCount() -1; 53 | for(int i = 0; i <= len; i++){ 54 | s = treePath.getPathComponent(i).toString(); 55 | if(i>0) str += String.valueOf(MainApp.dot); 56 | if(i == len) { 57 | str += Kit.pstr(s)[1]; 58 | }else{ 59 | str += s.substring(2); 60 | } 61 | } 62 | str = StringUtils.replace(str, String.valueOf(MainApp.dot)+"[", "["); 63 | str = StringUtils.substring(str, 5); 64 | return str; 65 | } 66 | /** 67 | * 复制相似路径节点键值对. 68 | * @param treeNode 69 | * @return 70 | */ 71 | public String copySimilarPathKeyValue(TreeNode treeNode){ 72 | String str = ""; 73 | String key = Kit.pstr(treeNode.toString())[1]; 74 | TreeNode node = treeNode.getParent(); 75 | if(node==null) return ""; 76 | node = node.getParent(); 77 | if(node == null) return ""; 78 | int count = node.getChildCount(); 79 | int size = 0; 80 | for(int i = 0; i < count; i++){ 81 | TreeNode child = node.getChildAt(i); 82 | if(child==null) continue; 83 | size = child.getChildCount(); 84 | for(int i2 = 0; i2 < size; i2++){ 85 | TreeNode tmp = child.getChildAt(i2); 86 | if(tmp==null)continue; 87 | String arr[] = Kit.pstr(tmp.toString()); 88 | if(key!=null && key.equals(arr[1])){ 89 | str += arr[2] + "\n"; 90 | } 91 | } 92 | } 93 | return str; 94 | } 95 | /** 96 | * 复制节点内容. 97 | * @param path 节点路径 98 | * @param isFormat 是否带格式 99 | * @return 100 | */ 101 | private String copyNodeContent(String path,boolean isFormat){ 102 | String str; 103 | String arr[] = StringUtils.split(path, String.valueOf(MainApp.dot)); 104 | //System.out.println("Get HashCode : " + tree.hashCode() + " . TabTitle : " + getTabTitle()); 105 | Object obj = jsonEleTreeMap.get(tree.hashCode()); 106 | if(arr.length<=0){ 107 | return ""; 108 | } 109 | for (String arr1 : arr) { 110 | int index = Kit.getIndex(arr1); 111 | String key = Kit.getKey(arr1); 112 | if (index == -1) { 113 | obj = ((JSONObject) obj).get(key); 114 | } else { 115 | obj = ((JSONObject) obj).getJSONArray(key).get(index); 116 | } 117 | } 118 | if (obj == null) { 119 | return ""; 120 | } 121 | if (isFormat) { 122 | str = JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.PrettyFormat); 123 | } else { 124 | str = JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue); 125 | } 126 | return str; 127 | } 128 | @Override 129 | public void actionPerformed(ActionEvent e) { 130 | if(obj==null) return; 131 | StringSelection stringSelection = null; 132 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 133 | if(optType == 4){ 134 | String path = copyTreeNodePath((TreePath)obj); 135 | path = StringUtils.replace(path, String.valueOf(MainApp.dot), "."); 136 | stringSelection = new StringSelection(path); 137 | clipboard.setContents(stringSelection, null); 138 | } 139 | else if(optType == 5){ 140 | stringSelection = new StringSelection(copySimilarPathKeyValue((TreeNode)obj)); 141 | clipboard.setContents(stringSelection, null); 142 | } 143 | else if(optType == 6 || optType == 7){ 144 | String path = copyTreeNodePath((TreePath)obj); 145 | boolean isForamt = false; 146 | if(optType == 7) isForamt = true; 147 | String str = copyNodeContent(path,isForamt); 148 | stringSelection = new StringSelection(str); 149 | clipboard.setContents(stringSelection, null); 150 | } 151 | else{ 152 | String str = obj.toString(); 153 | String[] arr = Kit.pstr(str); 154 | if("".equals(arr[2])){ 155 | arr[2] = "null"; 156 | } 157 | if (optType == 1 || optType == 2){ 158 | stringSelection = new StringSelection(arr[optType]); 159 | } else if (optType == 3) { 160 | stringSelection = new StringSelection(str.substring(2)); 161 | }else if(optType == 8){ 162 | String temp = "\"" + arr[1] + "\",\"" + arr[2] + "\""; 163 | stringSelection = new StringSelection(temp); 164 | } 165 | clipboard.setContents(stringSelection, null); 166 | } 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | cy.jsonview 7 | jsonview 8 | 2.3.3 9 | jar 10 | 11 | JsonView 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | dom4j 20 | dom4j 21 | 1.6.1 22 | 23 | 24 | com.alibaba 25 | fastjson 26 | 1.2.75 27 | 28 | 29 | commons-lang 30 | commons-lang 31 | 2.6 32 | 33 | 34 | 35 | 36 | com.fifesoft 37 | rsyntaxtextarea 38 | 2.6.1 39 | 40 | 41 | org.netbeans 42 | org-netbeans-swing-tabcontrol 43 | 200804211638 44 | 45 | 46 | org.netbeans 47 | org-openide-awt 48 | 200804211638 49 | 50 | 51 | org.netbeans 52 | org-openide-util 53 | 200804211638 54 | 55 | 56 | org.netbeans 57 | org-openide-windows 58 | 200804211638 59 | 60 | 61 | 62 | 63 | 64 | JsonView 65 | 66 | 67 | org.apache.maven.plugins 68 | maven-compiler-plugin 69 | 70 | 1.8 71 | 1.8 72 | UTF-8 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-shade-plugin 78 | 3.2.1 79 | 80 | 81 | package 82 | 83 | shade 84 | 85 | 86 | 87 | 88 | true 89 | shaded 90 | 91 | 93 | cy.jsonview.code.MainApp 94 | 95 | 96 | 97 | 98 | 99 | 100 | com.akathist.maven.plugins.launch4j 101 | launch4j-maven-plugin 102 | 1.7.25 103 | 104 | 105 | l4j-clui 106 | package 107 | 108 | launch4j 109 | 110 | 111 | gui 112 | ${project.build.directory}/${artifactId}-${version}-shaded.jar 113 | ${project.build.directory}/jsonView.exe 114 | http://java.com/download 115 | 116 | cy.jsonview.code.MainApp 117 | anything 118 | 119 | src/main/resources/json.ico 120 | 121 | 1.8.0 122 | preferJre 123 | 124 | 125 | 1.0.0.0 126 | ${project.version} 127 | ${project.name} 128 | 2019 藏言 129 | 1.0.0.0 130 | 1.0.0.0 131 | ${project.name} 132 | 藏言 133 | jsonView 134 | jsonView.exe 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-antrun-plugin 144 | 145 | 146 | package 147 | 148 | run 149 | 150 | 151 | 152 | 156 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | src/main/java 170 | false 171 | 172 | **/*.* 173 | 174 | 175 | 176 | src/main/resources 177 | false 178 | 179 | **/*.* 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/listener/FindActionListener.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.listener; 2 | 3 | import cy.jsonview.code.SelCompUtil; 4 | import java.awt.FlowLayout; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | import java.awt.event.WindowEvent; 8 | import java.awt.event.WindowListener; 9 | import java.util.ArrayList; 10 | import java.util.Enumeration; 11 | import java.util.List; 12 | import javax.swing.JButton; 13 | import javax.swing.JDialog; 14 | import javax.swing.JFrame; 15 | import javax.swing.JTextArea; 16 | import javax.swing.JTextField; 17 | import javax.swing.JTree; 18 | import javax.swing.text.BadLocationException; 19 | import javax.swing.text.Document; 20 | import javax.swing.text.Segment; 21 | import javax.swing.tree.DefaultMutableTreeNode; 22 | import javax.swing.tree.TreeNode; 23 | import javax.swing.tree.TreePath; 24 | import org.netbeans.swing.tabcontrol.TabbedContainer; 25 | 26 | /** 27 | * 28 | * @author cangyan 29 | */ 30 | public class FindActionListener implements ActionListener{ 31 | private boolean isTxtFindDlgOpen = false; 32 | private boolean isTreeFinDlgdOpen = false; 33 | private final List treePathLst; 34 | private final JFrame frame; 35 | private final TabbedContainer tabbedContainer; 36 | private final int type; 37 | private final String dlgTitle; 38 | private int curPos = 0; 39 | private JDialog openDlg; 40 | public FindActionListener(JFrame frame,TabbedContainer tabbedContainer,int type,String dlgTitle){ 41 | treePathLst = new ArrayList(); 42 | this.frame = frame; 43 | this.tabbedContainer = tabbedContainer; 44 | this.type = type; 45 | this.dlgTitle = dlgTitle; 46 | } 47 | 48 | 49 | 50 | private JDialog createDialog(){ 51 | JDialog dlg = new JDialog(frame); 52 | dlg.setTitle(dlgTitle); 53 | dlg.setModal(false); 54 | dlg.setSize(550,70); 55 | dlg.setResizable(false); 56 | dlg.setLocationRelativeTo(frame); 57 | return dlg; 58 | } 59 | 60 | @Override 61 | public void actionPerformed(ActionEvent e) { 62 | openDlg = createDialog(); 63 | java.awt.Container pane = openDlg.getContentPane(); 64 | FlowLayout layout = new FlowLayout(FlowLayout.LEFT); 65 | pane.setLayout(layout); 66 | JButton btnFind = new JButton("查找"); 67 | JButton btnNext = new JButton("下一个"); 68 | JButton btnPrev = new JButton("上一个"); 69 | final JTextField textFieldFind = new JTextField(50); 70 | pane.add(textFieldFind); 71 | pane.add(btnFind); 72 | pane.add(btnPrev); 73 | pane.add(btnNext); 74 | //从头开始查找 75 | btnFind.addActionListener(new ActionListener() { 76 | @Override 77 | public void actionPerformed(ActionEvent e) { 78 | boolean flag = false; 79 | modifyDialgTitle(flag,-1); 80 | if(type==1){ 81 | flag = startSegmentFindOrReplaceOperation(textFieldFind.getText(), true, true,true); 82 | }else{ 83 | findTreeChildValue(textFieldFind.getText(),treePathLst); 84 | if(!treePathLst.isEmpty()){ 85 | flag = true; 86 | } 87 | } 88 | modifyDialgTitle(flag,1); 89 | } 90 | }); 91 | //向下查找 92 | btnNext.addActionListener(new ActionListener() { 93 | @Override 94 | public void actionPerformed(ActionEvent e) { 95 | boolean flag = false; 96 | modifyDialgTitle(flag,-1); 97 | //JTree tree = getTree(); 98 | if(type==1){ 99 | flag = startSegmentFindOrReplaceOperation(textFieldFind.getText(), true, true,false); 100 | }else{ 101 | curPos++; 102 | if(curPos=0){ 127 | tree.setSelectionPath(treePathLst.get(curPos)); 128 | tree.scrollPathToVisible(treePathLst.get(curPos)); 129 | flag = true; 130 | }else{ 131 | curPos = 0; 132 | } 133 | } 134 | modifyDialgTitle(flag,1); 135 | } 136 | }); 137 | 138 | openDlg.addWindowListener(new WindowListener() { 139 | @Override 140 | public void windowOpened(WindowEvent e) {} 141 | @Override 142 | public void windowClosing(WindowEvent e) { 143 | treePathLst.clear(); 144 | if(type == 1){ 145 | isTxtFindDlgOpen = false; 146 | }else{ 147 | isTreeFinDlgdOpen = false; 148 | } 149 | System.gc(); 150 | } 151 | @Override 152 | public void windowClosed(WindowEvent e) { } 153 | @Override 154 | public void windowIconified(WindowEvent e) {} 155 | @Override 156 | public void windowDeiconified(WindowEvent e) {} 157 | @Override 158 | public void windowActivated(WindowEvent e) {} 159 | @Override 160 | public void windowDeactivated(WindowEvent e) {} 161 | }); 162 | 163 | openDlg.setVisible(true); 164 | 165 | if(type == 1){ 166 | isTxtFindDlgOpen = true; 167 | }else{ 168 | isTreeFinDlgdOpen = true; 169 | } 170 | } 171 | 172 | private void modifyDialgTitle(boolean flag,int n){ 173 | String[] tmp = openDlg.getTitle().split("-"); 174 | if(n==-1){ 175 | openDlg.setTitle(tmp[0] + "-" + " =="); 176 | return; 177 | } 178 | if (flag) { 179 | openDlg.setTitle(tmp[0] + "-" + " 找到了^_^"); 180 | } else { 181 | openDlg.setTitle(tmp[0] + "-" + " 没找到╮(╯_╰)╭"); 182 | } 183 | } 184 | public boolean startSegmentFindOrReplaceOperation(String key, boolean ignoreCase, boolean down,boolean isFirst) { 185 | int length = key.length(); 186 | JTextArea textArea = SelCompUtil.getTextArea(tabbedContainer); 187 | Document doc = textArea.getDocument(); 188 | int offset = textArea.getCaretPosition(); 189 | int charsLeft = doc.getLength() - offset; 190 | if(charsLeft <=0 ){ 191 | offset = 0; 192 | charsLeft = doc.getLength() - offset; 193 | } 194 | if (!down) { 195 | offset -= length; 196 | offset--; 197 | charsLeft = offset; 198 | } 199 | if(isFirst){ 200 | offset = 0; 201 | charsLeft = doc.getLength() - offset; 202 | } 203 | Segment text = new Segment(); 204 | text.setPartialReturn(true); 205 | try { 206 | while (charsLeft > 0) { 207 | doc.getText(offset, length, text); 208 | if ((ignoreCase == true && text.toString().equalsIgnoreCase(key)) 209 | || (ignoreCase == false && text.toString().equals(key))) { 210 | textArea.requestFocus();////焦点,才能能看到效果 211 | textArea.setSelectionStart(offset); 212 | textArea.setSelectionEnd(offset + length); 213 | return true; 214 | } 215 | charsLeft--; 216 | if (down) { 217 | offset++; 218 | } else { 219 | offset--; 220 | } 221 | 222 | } 223 | } catch (BadLocationException e) { 224 | } 225 | return false; 226 | } 227 | 228 | private void findTreeChildValue(String findText,List treePathLst) { 229 | JTree tree = SelCompUtil.getTree(tabbedContainer); 230 | DefaultMutableTreeNode root = (DefaultMutableTreeNode)tree.getModel().getRoot(); 231 | Enumeration e = root.depthFirstEnumeration(); 232 | treePathLst.clear(); 233 | curPos = 0; 234 | while (e.hasMoreElements()) { 235 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.nextElement(); 236 | if (node.isLeaf()) { 237 | String str = node.toString(); 238 | if (str.substring(2).contains(findText)) { 239 | tree.expandPath(new TreePath(node.getPath())); 240 | TreePath tp = expandTreeNode(tree,node.getPath(), true); 241 | treePathLst.add(tp); 242 | } 243 | } 244 | } 245 | if(!treePathLst.isEmpty()){ 246 | tree.setSelectionPath(treePathLst.get(0)); 247 | tree.scrollPathToVisible(treePathLst.get(0)); 248 | } 249 | // return treePathLst; 250 | } 251 | 252 | private TreePath expandTreeNode(JTree tree,TreeNode[] arr, Boolean expand) { 253 | TreePath[] tp = new TreePath[arr.length]; 254 | tp[0] = new TreePath(arr[0]); 255 | int pos = 0; 256 | for (int i = 1; i < arr.length; i++) { 257 | tp[i] = tp[i - 1].pathByAddingChild(arr[i]); 258 | } 259 | for (int i = 0; i < arr.length; i++) { 260 | if (expand) { 261 | tree.expandPath(tp[i]); 262 | } else { 263 | tree.collapsePath(tp[i]); 264 | } 265 | pos = i; 266 | } 267 | return tp[pos]; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/code/Kit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package cy.jsonview.code; 7 | 8 | import java.io.IOException; 9 | import java.io.StringReader; 10 | import java.io.StringWriter; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import javax.swing.ImageIcon; 16 | import javax.swing.tree.DefaultMutableTreeNode; 17 | import javax.xml.parsers.DocumentBuilderFactory; 18 | import javax.xml.parsers.ParserConfigurationException; 19 | import org.apache.commons.lang.ClassUtils; 20 | import org.apache.commons.lang.StringUtils; 21 | import org.dom4j.DocumentException; 22 | import org.dom4j.DocumentHelper; 23 | import org.dom4j.io.XMLWriter; 24 | import org.w3c.dom.Document; 25 | import org.w3c.dom.Node; 26 | import org.w3c.dom.NodeList; 27 | import org.xml.sax.InputSource; 28 | import org.xml.sax.SAXException; 29 | 30 | 31 | /** 32 | * 33 | * @author CangYan 34 | */ 35 | public class Kit { 36 | public final static String split = " : "; 37 | 38 | public final static String sign = "-" ; 39 | 40 | public final static String cNull = "k"; 41 | public final static String cNum = "n"; 42 | public final static String cObj = "o"; 43 | public final static String cArr = "a"; 44 | public final static String cStr = "v"; 45 | public final static String cBool = "b"; 46 | 47 | public final static String sNull = cNull + sign; 48 | public final static String sNum = cNum + sign; 49 | public final static String sObj = cObj + sign; 50 | public final static String sArr = cArr + sign; 51 | public final static String sStr = cStr + sign; 52 | public final static String sBool = cBool + sign; 53 | 54 | public final static String array = "Array"; 55 | public final static String object = "Object"; 56 | public static String baseResPath = "cy/jsonview/resources/"; 57 | public static String QUOT = "\""; 58 | 59 | public static DefaultMutableTreeNode nullNode(String key){ 60 | return treeNode(sNull + key + split + ""); 61 | } 62 | public static DefaultMutableTreeNode nullNode(int index){ 63 | return nullNode(fkey(index)); 64 | } 65 | 66 | public static DefaultMutableTreeNode numNode(String key,String val){ 67 | return treeNode(sNum + key + split + val); 68 | } 69 | public static DefaultMutableTreeNode numNode(int index,String val){ 70 | return numNode(fkey(index),val); 71 | } 72 | 73 | public static DefaultMutableTreeNode boolNode(String key,Boolean val){ 74 | String sVal = "false"; 75 | if (val){ 76 | sVal = "true"; 77 | } 78 | return treeNode(sBool + key + split + sVal); 79 | } 80 | 81 | public static DefaultMutableTreeNode boolNode(int index,Boolean val){ 82 | return boolNode(fkey(index),val); 83 | } 84 | 85 | public static DefaultMutableTreeNode strNode(String key,String val){ 86 | return treeNode(sStr + key + split +"\"" + val + "\""); 87 | } 88 | public static DefaultMutableTreeNode strNode(int index,String val){ 89 | return strNode(fkey(index),val); 90 | } 91 | 92 | public static DefaultMutableTreeNode objNode(String key){ 93 | return treeNode(sObj+key); 94 | } 95 | 96 | public static DefaultMutableTreeNode objNode(int index){ 97 | return objNode(fkey(index)); 98 | } 99 | 100 | public static DefaultMutableTreeNode arrNode(String key){ 101 | return treeNode(sArr+key); 102 | } 103 | 104 | public static DefaultMutableTreeNode arrNode(int index){ 105 | return arrNode(fkey(index)); 106 | } 107 | 108 | 109 | public static DefaultMutableTreeNode treeNode(String str){ 110 | return new DefaultMutableTreeNode(str); 111 | } 112 | 113 | public static DefaultMutableTreeNode treeNode(String type,int index,String val){ 114 | return treeNode(type +"[" + index + "]"); 115 | } 116 | 117 | public static String fkey(int index){ 118 | return "[" + index + "]"; 119 | } 120 | 121 | //"a-[" + i + "]" 122 | public static String fArrKey(int index){ 123 | return sArr + fkey(index); 124 | } 125 | 126 | 127 | public static int getIndex(String str){ 128 | int index = -1; 129 | if(str==null||str.length()==0) return index; 130 | index = str.lastIndexOf("["); 131 | if(index>=0){ 132 | try{ 133 | index = Integer.parseInt(str.substring(index+1,str.length()-1)); 134 | }catch(Exception ex){ 135 | index = -1; 136 | } 137 | } 138 | return index; 139 | } 140 | public static String getKey(String str){ 141 | int index = -1; 142 | if(str==null||str.length()==0) return str; 143 | index = str.lastIndexOf("["); 144 | if(index>=0){ 145 | return str.substring(0,index); 146 | } 147 | StringBuffer sb = null; 148 | return str; 149 | 150 | } 151 | 152 | public static String[] pstr(String str){ 153 | String arr[] = new String[3];//类型,key,value 154 | arr[0] = str.substring(0,1); 155 | int i = str.indexOf(Kit.split); 156 | // if(i<0) return arr; 157 | if(Kit.cArr.equals(arr[0])){ 158 | arr[1] = str.substring(2); 159 | arr[2] = Kit.array; 160 | }else if(Kit.cObj.equals(arr[0])){ 161 | arr[1] = str.substring(2); 162 | arr[2] = Kit.object; 163 | }else if(Kit.cStr.equals(arr[0])){ 164 | arr[1] = str.substring(2,i); 165 | arr[2] = str.substring(i+4,str.length()-1); 166 | }else{ 167 | arr[1] = str.substring(2,i); 168 | arr[2] = str.substring(i+3,str.length()); 169 | } 170 | return arr; 171 | } 172 | 173 | public static Map xmlToMap(String xml) throws SAXException, IOException, ParserConfigurationException { 174 | DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 175 | docBuilderFactory.setNamespaceAware(true); 176 | Document doc = docBuilderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); 177 | Map rootMap = new HashMap(); 178 | Map nodeMap = new HashMap(); 179 | Node node = doc.getDocumentElement(); 180 | xmlConversion(node, nodeMap); 181 | rootMap.put(node.getLocalName(), nodeMap); 182 | return rootMap; 183 | } 184 | private static void xmlConversion(Node node, Map nodeMap) { 185 | if (node.hasChildNodes()) { 186 | //Map nodeMap = new HashMap(); 187 | NodeList childList = node.getChildNodes(); 188 | for (int i = 0; i < childList.getLength(); i++) { 189 | Node childNode = childList.item(i); 190 | if (childNode.hasChildNodes()) { 191 | int len = childNode.getChildNodes().getLength(); 192 | short nodeType = childNode.getFirstChild().getNodeType(); 193 | if (len == 1 && nodeType == Node.TEXT_NODE) { 194 | String keyName = childNode.getLocalName(); 195 | String value = childNode.getFirstChild().getNodeValue(); 196 | if (null == nodeMap) { 197 | nodeMap = new HashMap(); 198 | } 199 | if (nodeMap.get(keyName) == null) { 200 | nodeMap.put(keyName, value); 201 | } else { 202 | //if (null != value) { 203 | List list = new ArrayList(); 204 | if (nodeMap.get(keyName) instanceof List) { 205 | list = (List) nodeMap.get(keyName); 206 | } else { 207 | list.add(nodeMap.get(keyName)); 208 | } 209 | list.add(value); 210 | nodeMap.put(keyName, list); 211 | //} 212 | } 213 | } else { 214 | HashMap map = new HashMap(); 215 | xmlConversion(childNode, map); 216 | // String keyName = childNode.getNodeName(); 217 | String keyName = childNode.getLocalName(); 218 | 219 | if (null == nodeMap) { 220 | nodeMap = new HashMap(); 221 | } 222 | if (null == nodeMap.get(keyName)) { 223 | nodeMap.put(keyName, map); 224 | } else { 225 | List list = new ArrayList(); 226 | if (nodeMap.get(keyName) instanceof List) { 227 | list = (List) nodeMap.get(keyName); 228 | } else { 229 | list.add(nodeMap.get(keyName)); 230 | } 231 | list.add(map); 232 | nodeMap.put(keyName, list); 233 | } 234 | if (childNode.getAttributes().getLength() > 0) { 235 | String tmpName = childNode.getAttributes().item(0).getNodeName(); 236 | String tmpValue = childNode.getAttributes().item(0).getNodeValue(); 237 | nodeMap.put(tmpName, tmpValue); 238 | } 239 | } 240 | }else if(childNode.getNodeType() == Node.ELEMENT_NODE){ 241 | if(StringUtils.isNotBlank(childNode.getLocalName())){ 242 | nodeMap.put(childNode.getLocalName(), null); 243 | } 244 | } 245 | } 246 | //rootMap.put(node.getLocalName(), nodeMap); 247 | } 248 | 249 | } 250 | 251 | public static String mapStringToJsonString(String mapstr){ 252 | mapstr = mapstr.replace(" ", ""); 253 | mapstr = mapstr.replace("\"", ""); 254 | mapstr = mapstr.replace("\r", ""); 255 | mapstr = mapstr.replace("\n", ""); 256 | mapstr = mapstr.replace("\t", ""); 257 | int len = mapstr.length() - 1; 258 | String json = ""; 259 | for (int i = 0; i <= len; i++) { 260 | char c = mapstr.charAt(i); 261 | char cp = 0; 262 | if (i < len) { 263 | cp = mapstr.charAt(i + 1); 264 | } 265 | char cr = 0; 266 | if (i > 0) { 267 | cr = mapstr.charAt(i - 1); 268 | } 269 | 270 | //{[{aaa= 271 | if (c == '{' || c == '[') { 272 | if (cp == '}' || cp == ']') { 273 | json = json + c + cp; 274 | i++; 275 | continue; 276 | } 277 | if (cp == '{' || cp == '[') { 278 | json += c; 279 | continue; 280 | } 281 | json = json + c + QUOT; 282 | continue; 283 | } 284 | //aa=aa ---> "aa":"aa" 285 | //aa={ ---> "aa":{ 286 | //aa=[ ---> "aa":[ 287 | //aa=,bb=bb ---> "aa":"","bb":"bb" 288 | if (c == '=') { 289 | if (cp == '{' || cp == '[') { 290 | json = json + QUOT + ":"; 291 | continue; 292 | } 293 | if (cp == ',') { 294 | json = json + QUOT + ":" + QUOT + QUOT + cp; 295 | i++; 296 | continue; 297 | } 298 | json = json + QUOT + ":" + QUOT; 299 | continue; 300 | } 301 | 302 | // ],[ ],{ ],b 303 | // },{ },[ },b 304 | // a,{ a,[ a,b 305 | // aaa=,bb=ccc 306 | if (c == ',') { 307 | if (cr == '}' || cr == ']') { 308 | if (cp == '{' || cp == '[') { 309 | json += c; 310 | continue; 311 | } 312 | json += c + QUOT; 313 | continue; 314 | } 315 | if (cp == '{' || cp == '[') { 316 | json = json + QUOT + c; 317 | continue; 318 | } 319 | json = json + QUOT + c + QUOT; 320 | continue; 321 | } 322 | 323 | // a]}]},ad=sd 324 | if (c == '}' || c == ']') { 325 | if (cr == '}' || cr == ']') { 326 | json += c; 327 | continue; 328 | } 329 | json = json + QUOT + c; 330 | continue; 331 | } 332 | json += c; 333 | } 334 | return json; 335 | } 336 | /* 337 | public static String formatXML(String xml,boolean isIndenting) throws ParserConfigurationException, SAXException, IOException{ 338 | DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 339 | docBuilderFactory.setNamespaceAware(true); 340 | Document doc = docBuilderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); 341 | OutputFormat format = new OutputFormat(doc); 342 | if(isIndenting){ 343 | format.setIndenting(true); 344 | }else{ 345 | System.out.println("##########################"); 346 | // format.setIndenting(false);//设置是否缩进,默认为true 347 | //format.setIndent(0);//设置缩进字符数 348 | format.setPreserveSpace(true); 349 | format.setOmitXMLDeclaration(true); 350 | format.setLineSeparator( "" ); 351 | 352 | //设置是否保持原来的格式,默认为 false 353 | } 354 | Writer out = new StringWriter(); 355 | XMLSerializer serializer = new XMLSerializer(out, format); 356 | serializer.serialize(doc); 357 | return out.toString(); 358 | } 359 | 360 | public static String formatXML2(String xml,boolean isIndenting) throws TransformerConfigurationException, TransformerException, ParserConfigurationException, SAXException, IOException{ 361 | DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 362 | docBuilderFactory.setNamespaceAware(true); 363 | Document doc = docBuilderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); 364 | System.out.println(doc.getTextContent()); 365 | TransformerFactory transFactory = TransformerFactory.newInstance(); 366 | Transformer transformer = transFactory.newTransformer(); 367 | 368 | //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); 369 | //transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 370 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 371 | DOMSource source = new DOMSource(); 372 | source.setNode(doc); 373 | StreamResult result = new StreamResult(); 374 | result.setOutputStream(outputStream); 375 | transformer.transform(source, result); 376 | return outputStream.toString(); 377 | } 378 | */ 379 | public static String formatXML(String xml,boolean isPrettyPrint) throws DocumentException, IOException{ 380 | org.dom4j.Document doc = DocumentHelper.parseText(xml); 381 | org.dom4j.io.OutputFormat format = null; 382 | if(isPrettyPrint){ 383 | format = org.dom4j.io.OutputFormat.createPrettyPrint(); 384 | format.setIndent(true); 385 | format.setIndentSize(4); 386 | }else{ 387 | format = org.dom4j.io.OutputFormat.createCompactFormat(); 388 | format.setSuppressDeclaration(true); 389 | } 390 | StringWriter sw = new StringWriter(); 391 | XMLWriter xw = new XMLWriter(sw, format); 392 | xw.setEscapeText(false); 393 | xw.write(doc); 394 | String s = sw.toString(); 395 | xw.flush(); 396 | return s; 397 | } 398 | } 399 | -------------------------------------------------------------------------------- /src/main/java/cy/jsonview/code/MainApp.java: -------------------------------------------------------------------------------- 1 | package cy.jsonview.code; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONArray; 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.alibaba.fastjson.parser.Feature; 7 | import com.alibaba.fastjson.serializer.SerializerFeature; 8 | import cy.jsonview.listener.FileOpenActionListener; 9 | import cy.jsonview.listener.FileSaveActionListener; 10 | import cy.jsonview.listener.FindActionListener; 11 | import cy.jsonview.listener.QuitActionListener; 12 | import cy.jsonview.listener.TabDataModelComplexListDataListener; 13 | import cy.jsonview.listener.TreeMouseListener; 14 | 15 | import java.awt.*; 16 | import java.awt.datatransfer.Clipboard; 17 | import java.awt.datatransfer.StringSelection; 18 | import java.awt.event.ActionEvent; 19 | import java.awt.event.ActionListener; 20 | import java.awt.event.ComponentEvent; 21 | import java.awt.event.ComponentListener; 22 | import java.awt.event.InputEvent; 23 | import java.awt.event.KeyEvent; 24 | import java.io.IOException; 25 | import java.net.URL; 26 | import java.util.*; 27 | import java.util.List; 28 | import javax.imageio.ImageIO; 29 | import javax.print.DocFlavor; 30 | import javax.swing.Icon; 31 | import javax.swing.ImageIcon; 32 | import javax.swing.JButton; 33 | import javax.swing.JDialog; 34 | import javax.swing.JLabel; 35 | import javax.swing.JMenu; 36 | import javax.swing.JMenuItem; 37 | import javax.swing.JPopupMenu; 38 | import javax.swing.JScrollPane; 39 | import javax.swing.JSplitPane; 40 | import javax.swing.JTextArea; 41 | import javax.swing.JTextField; 42 | import javax.swing.JToolBar; 43 | import javax.swing.JTree; 44 | import javax.swing.KeyStroke; 45 | import javax.swing.UnsupportedLookAndFeelException; 46 | import javax.swing.event.PopupMenuEvent; 47 | import javax.swing.event.PopupMenuListener; 48 | import javax.swing.tree.DefaultMutableTreeNode; 49 | import javax.swing.tree.DefaultTreeCellRenderer; 50 | import javax.swing.tree.DefaultTreeModel; 51 | import javax.xml.parsers.ParserConfigurationException; 52 | 53 | import org.apache.commons.lang.StringEscapeUtils; 54 | import org.apache.commons.lang.StringUtils; 55 | import org.dom4j.DocumentException; 56 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; 57 | import org.fife.ui.rsyntaxtextarea.SyntaxConstants; 58 | import org.fife.ui.rsyntaxtextarea.SyntaxScheme; 59 | import org.fife.ui.rsyntaxtextarea.Token; 60 | import org.fife.ui.rtextarea.Gutter; 61 | import org.fife.ui.rtextarea.RTextScrollPane; 62 | import org.netbeans.swing.tabcontrol.DefaultTabDataModel; 63 | import org.netbeans.swing.tabcontrol.TabData; 64 | import org.netbeans.swing.tabcontrol.TabDataModel; 65 | import org.netbeans.swing.tabcontrol.TabbedContainer; 66 | import org.openide.util.Exceptions; 67 | import org.xml.sax.SAXException; 68 | 69 | public class MainApp extends javax.swing.JFrame { 70 | private javax.swing.JMenuBar jMenuBar1; 71 | private javax.swing.JFrame frame; 72 | private TabDataModel tabDataModel; 73 | private TabbedContainer tabbedContainer; 74 | private ResourceBundle bundle; 75 | private final Map jsonEleTreeMap = new HashMap(); 76 | public static final char dot = 30; 77 | public String baseResPath = "cy/jsonview/resources/"; 78 | 79 | public MainApp() { 80 | initComponents(); 81 | this.setSize(1000, 600); 82 | setLocationRelativeTo(getOwner()); 83 | setDefaultCloseOperation(EXIT_ON_CLOSE); 84 | setTitle("CyJsonView 2.3.3 @藏言"); 85 | initTitleIcon(); 86 | setVisible(true); 87 | } 88 | 89 | private int getTabIndex() { 90 | return tabbedContainer.getSelectionModel().getSelectedIndex(); 91 | } 92 | 93 | private void initTitleIcon() { 94 | try { 95 | URL url = this.getClass().getClassLoader().getResource("json.gif"); 96 | this.setIconImage(ImageIO.read(url)); 97 | } catch (Exception e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | private RSyntaxTextArea getTextArea() { 103 | return SelCompUtil.getTextArea(tabbedContainer); 104 | } 105 | 106 | private JMenu createFileMenu() { 107 | JMenu menu = new javax.swing.JMenu(); 108 | menu.setText("文件"); 109 | JMenuItem menuItemOpenFile = createMenuItem("打开文件", KeyEvent.VK_O); 110 | menuItemOpenFile.addActionListener(new FileOpenActionListener(frame, tabbedContainer, "打开文件对话框")); 111 | menu.add(menuItemOpenFile); 112 | 113 | JMenuItem menuItemSaveFile = createMenuItem("保存文件", KeyEvent.VK_S); 114 | menuItemSaveFile.addActionListener(new FileSaveActionListener(frame, tabbedContainer, "保存文件对话框")); 115 | 116 | menu.add(menuItemSaveFile); 117 | 118 | JMenuItem exitMenuItem = new JMenuItem(); 119 | exitMenuItem.addActionListener(new QuitActionListener()); 120 | exitMenuItem.setText("退出"); 121 | menu.add(exitMenuItem); 122 | return menu; 123 | } 124 | 125 | 126 | private JMenu createAboutMenu() { 127 | JMenu menuAbout = new javax.swing.JMenu(); 128 | menuAbout.setText("关于"); 129 | JMenuItem menuItemLayout = createMenuItem("关于", KeyEvent.VK_A); 130 | menuItemLayout.addActionListener(new java.awt.event.ActionListener() { 131 | @Override 132 | public void actionPerformed(java.awt.event.ActionEvent evt) { 133 | AboutDialog.show(frame); 134 | } 135 | }); 136 | menuAbout.add(menuItemLayout); 137 | return menuAbout; 138 | } 139 | 140 | 141 | private JMenu createToolMenu() { 142 | JMenu toolMenu = new javax.swing.JMenu(); 143 | toolMenu.setText("工具"); 144 | 145 | JMenuItem menuItemLayout = createMenuItem("布局", KeyEvent.VK_L); 146 | menuItemLayout.addActionListener(new java.awt.event.ActionListener() { 147 | @Override 148 | public void actionPerformed(java.awt.event.ActionEvent evt) { 149 | changeLayout(); 150 | } 151 | }); 152 | toolMenu.add(menuItemLayout); 153 | 154 | JMenuItem menuItemNew = createMenuItem("新标签", KeyEvent.VK_N); 155 | menuItemNew.addActionListener(new java.awt.event.ActionListener() { 156 | @Override 157 | public void actionPerformed(java.awt.event.ActionEvent evt) { 158 | addTab("NewTab", true); 159 | } 160 | }); 161 | toolMenu.add(menuItemNew); 162 | 163 | return toolMenu; 164 | } 165 | 166 | private JMenuItem createMenuItem(String name, int keyCode) { 167 | JMenuItem menuItem = new JMenuItem(); 168 | menuItem.setAccelerator(KeyStroke.getKeyStroke(keyCode, InputEvent.CTRL_MASK)); 169 | menuItem.setText(name); 170 | return menuItem; 171 | } 172 | 173 | private void initComponents() { 174 | frame = this; 175 | jMenuBar1 = new javax.swing.JMenuBar(); 176 | 177 | initTabbedContainer(); 178 | jMenuBar1.add(createFileMenu()); 179 | jMenuBar1.add(createEditMenu()); 180 | jMenuBar1.add(createToolMenu()); 181 | jMenuBar1.add(createAboutMenu()); 182 | 183 | setJMenuBar(jMenuBar1); 184 | 185 | this.add(createToolBar(), BorderLayout.PAGE_START); 186 | this.add(tabbedContainer, BorderLayout.CENTER); 187 | pack(); 188 | 189 | } 190 | 191 | private JMenu createEditMenu() { 192 | JMenu editMenu = new javax.swing.JMenu(); 193 | editMenu.setText("编辑"); 194 | JMenuItem menuItemClean = createMenuItem("清除", KeyEvent.VK_D); 195 | menuItemClean.addActionListener(new java.awt.event.ActionListener() { 196 | @Override 197 | public void actionPerformed(java.awt.event.ActionEvent evt) { 198 | getTextArea().setText(""); 199 | } 200 | }); 201 | editMenu.add(menuItemClean); 202 | 203 | JMenuItem menuItemFormat = createMenuItem("格式化", KeyEvent.VK_F); 204 | menuItemFormat.addActionListener(new ActionListener() { 205 | @Override 206 | public void actionPerformed(ActionEvent evt) { 207 | formatJson(); 208 | } 209 | }); 210 | editMenu.add(menuItemFormat); 211 | return editMenu; 212 | } 213 | 214 | public void setFrameTitle(String title) { 215 | this.setTitle(title); 216 | } 217 | 218 | private void initTabbedContainer() { 219 | TabData tabData = newTabData("Welcome!", "This is a Tab!", null); 220 | tabDataModel = new DefaultTabDataModel(new TabData[]{tabData}); 221 | tabbedContainer = new TabbedContainer(tabDataModel, TabbedContainer.TYPE_EDITOR); 222 | tabbedContainer.getSelectionModel().setSelectedIndex(0); 223 | tabbedContainer.setShowCloseButton(true); 224 | tabDataModel.addComplexListDataListener(new TabDataModelComplexListDataListener(jsonEleTreeMap)); 225 | /* 226 | tabbedContainer.addActionListener(new ActionListener() { 227 | @Override 228 | public void actionPerformed(ActionEvent e) { 229 | //System.out.println("@@@:TabbedContainerActionCommand = "+e.getActionCommand()); 230 | if("select".equalsIgnoreCase(e.getActionCommand())){ 231 | treePathLst.clear(); 232 | } 233 | } 234 | }); 235 | */ 236 | 237 | } 238 | 239 | private TabData newTabData(String tabName, String tabTip, Icon icon) { 240 | final JSplitPane splitPane = new JSplitPane(); 241 | splitPane.addComponentListener(new ComponentListener() { 242 | @Override 243 | public void componentResized(ComponentEvent e) { 244 | splitPane.setDividerLocation(0.6); 245 | } 246 | 247 | @Override 248 | public void componentMoved(ComponentEvent e) { 249 | } 250 | 251 | @Override 252 | public void componentShown(ComponentEvent e) { 253 | } 254 | 255 | @Override 256 | public void componentHidden(ComponentEvent e) { 257 | } 258 | }); 259 | 260 | RSyntaxTextArea textArea = newTextArea(); 261 | RTextScrollPane sp = new RTextScrollPane(textArea); 262 | sp.setFoldIndicatorEnabled(true); 263 | sp.setIconRowHeaderEnabled(true); 264 | Gutter gutter = sp.getGutter(); 265 | gutter.setBookmarkingEnabled(true); 266 | URL url = getClass().getClassLoader().getResource("cy/jsonview/resources/bookmark.png"); 267 | gutter.setBookmarkIcon(new ImageIcon(url)); 268 | splitPane.setLeftComponent(sp); 269 | splitPane.setRightComponent(new JScrollPane(newTree())); 270 | TabData tabData = new TabData(splitPane, icon, tabName, tabTip); 271 | return tabData; 272 | } 273 | 274 | private void addPopupMenuItemCopyXml(RSyntaxTextArea textArea) { 275 | JPopupMenu popMenu = textArea.getPopupMenu(); 276 | popMenu.addPopupMenuListener(new PopupMenuListener() { 277 | @Override 278 | public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 279 | String text = getTextArea().getText(); 280 | JPopupMenu popMenu = getTextArea().getPopupMenu(); 281 | JMenuItem mtCopyXml = (JMenuItem) popMenu.getComponent(popMenu.getComponentCount() - 1); 282 | int num = text.indexOf(""); 283 | if (num >= 0 && num < 2) { 284 | mtCopyXml.setEnabled(true); 285 | } else { 286 | mtCopyXml.setEnabled(false); 287 | } 288 | } 289 | 290 | @Override 291 | public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 292 | } 293 | 294 | @Override 295 | public void popupMenuCanceled(PopupMenuEvent e) { 296 | } 297 | }); 298 | 299 | JMenuItem mtCopyXml = new JMenuItem("复制XML"); 300 | mtCopyXml.addActionListener(new ActionListener() { 301 | @Override 302 | public void actionPerformed(ActionEvent e) { 303 | String xml = getTextArea().getText(); 304 | StringSelection stringSelection; 305 | try { 306 | xml = Kit.formatXML(xml, false); 307 | xml = StringUtils.remove(xml, ""); 308 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 309 | stringSelection = new StringSelection(xml); 310 | clipboard.setContents(stringSelection, null); 311 | } catch (HeadlessException ex) { 312 | Exceptions.printStackTrace(ex); 313 | } catch (IOException ex) { 314 | Exceptions.printStackTrace(ex); 315 | } catch (DocumentException ex) { 316 | Exceptions.printStackTrace(ex); 317 | } 318 | } 319 | }); 320 | popMenu.add(mtCopyXml); 321 | } 322 | 323 | private RSyntaxTextArea newTextArea() { 324 | RSyntaxTextArea textArea = new RSyntaxTextArea(); 325 | textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); 326 | textArea.setCodeFoldingEnabled(true); 327 | textArea.setAntiAliasingEnabled(true); 328 | textArea.setAutoscrolls(true); 329 | textArea.setMarkOccurrences(true); 330 | textArea.setTabSize(4); 331 | textArea.setAnimateBracketMatching(true); 332 | textArea.setPaintTabLines(true); 333 | addPopupMenuItemCopyXml(textArea); 334 | 335 | //textArea.setLineWrap(true); 336 | 337 | SyntaxScheme scheme = textArea.getSyntaxScheme(); 338 | scheme.getStyle(Token.LITERAL_STRING_DOUBLE_QUOTE).foreground = Color.BLUE; 339 | scheme.getStyle(Token.LITERAL_NUMBER_DECIMAL_INT).foreground = new Color(164, 0, 0); 340 | scheme.getStyle(Token.LITERAL_NUMBER_FLOAT).foreground = new Color(164, 0, 0); 341 | scheme.getStyle(Token.LITERAL_BOOLEAN).foreground = Color.RED; 342 | scheme.getStyle(Token.OPERATOR).foreground = Color.BLACK; 343 | textArea.revalidate(); 344 | //textArea.addMouseListener(new MainView.TextAreaMouseListener()); 345 | return textArea; 346 | } 347 | 348 | private JTree newTree() { 349 | DefaultMutableTreeNode root = new DefaultMutableTreeNode("o-JSON"); 350 | DefaultTreeModel model = new DefaultTreeModel(root); 351 | JTree tree = new JTree(model); 352 | setNodeIcon(tree); 353 | tree.addMouseListener(new TreeMouseListener(tree, jsonEleTreeMap)); 354 | return tree; 355 | } 356 | 357 | private void formatJson() { 358 | //格式化字符串 359 | JTextArea ta = getTextArea(); 360 | String text = ta.getText(); 361 | char c = text.trim().charAt(0); 362 | if (c == '{' || c == '[') { 363 | buildJson(text); 364 | } 365 | } 366 | 367 | private void buildJson(String text) { 368 | try { 369 | Object jsonobj = JSON.parse(text, Feature.AllowSingleQuotes); 370 | String jsonText = JSON.toJSONString(jsonobj, SerializerFeature.WriteMapNullValue, SerializerFeature.PrettyFormat); 371 | if (jsonText != null) { 372 | jsonText = StringEscapeUtils.unescapeJava(jsonText); 373 | //getTextArea().setAutoIndentEnabled(true); 374 | getTextArea().setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); 375 | getTextArea().setText(jsonText); 376 | } 377 | createTree(jsonobj); 378 | } catch (Exception ex) { 379 | Exceptions.printStackTrace(ex); 380 | showMessageDialog("非法JSON字符串!", ex.getMessage()); 381 | } 382 | System.gc(); 383 | } 384 | 385 | private JTree getTree() { 386 | return SelCompUtil.getTree(tabbedContainer); 387 | } 388 | 389 | private String getTabTitle() { 390 | return tabDataModel.getTab(getTabIndex()).getText(); 391 | } 392 | 393 | private void analyzeJsonObject(JSONObject jobj, DefaultMutableTreeNode treeNode) { 394 | if (jobj.isEmpty()) { 395 | return; 396 | } 397 | TreeMap jsonMap = new TreeMap<>(); 398 | for(Map.Entry entry : jobj.entrySet()){ 399 | Object key = entry.getKey(); 400 | jsonMap.put(key.toString(),entry.getValue()); 401 | } 402 | // 403 | // List keyList = new ArrayList(); 404 | // Iterator itkey = jobj.keySet().iterator(); 405 | // while (itkey.hasNext()) { 406 | // keyList.add(itkey.next()); 407 | // } 408 | // Collections.sort(keyList); 409 | for (Map.Entry entry : jsonMap.entrySet()) { 410 | //Object obj = jobj.get(key); 411 | String key = entry.getKey(); 412 | Object obj = entry.getValue(); 413 | if (obj instanceof JSONObject) { 414 | DefaultMutableTreeNode node = Kit.objNode(key); 415 | analyzeJsonObject((JSONObject) obj, node); 416 | treeNode.add(node); 417 | } else if (obj instanceof JSONArray) { 418 | analyzeJsonArray((JSONArray) obj, treeNode, key); 419 | } else if (obj instanceof String) { 420 | treeNode.add(Kit.strNode(key, (String) obj)); 421 | } else if (obj instanceof Number) { 422 | treeNode.add(Kit.numNode(key, obj.toString())); 423 | } else if (obj instanceof Boolean) { 424 | treeNode.add(Kit.boolNode(key, (Boolean) obj)); 425 | } else if (obj == null) { 426 | treeNode.add(Kit.nullNode(key)); 427 | } 428 | } 429 | } 430 | 431 | private void analyzeJsonArray(JSONArray jarr, DefaultMutableTreeNode rootNode, String key) { 432 | int index = 0; 433 | DefaultMutableTreeNode topNode = Kit.arrNode(key); 434 | for (Iterator it = jarr.iterator(); it.hasNext(); ) { 435 | Object el = it.next(); 436 | if (el instanceof JSONObject) { 437 | DefaultMutableTreeNode childNode = Kit.objNode(index); 438 | analyzeJsonObject((JSONObject) el, childNode); 439 | topNode.add(childNode); 440 | } else if (el instanceof JSONArray) { 441 | analyzeJsonArray((JSONArray) el, topNode, Kit.fkey(index)); 442 | } else if (el instanceof String) { 443 | topNode.add(Kit.strNode(Kit.fkey(index), el.toString())); 444 | } else if (el instanceof Number) { 445 | topNode.add(Kit.numNode(Kit.fkey(index), el.toString())); 446 | } else if (el instanceof Boolean) { 447 | topNode.add(Kit.boolNode(Kit.fkey(index), (Boolean) el)); 448 | } else if (el == null) { 449 | topNode.add(Kit.nullNode(Kit.fkey(index))); 450 | } 451 | ++index; 452 | } 453 | rootNode.add(topNode); 454 | } 455 | 456 | private void setNodeIcon(JTree tree) { 457 | tree.setCellRenderer(new DefaultTreeCellRenderer() { 458 | @Override 459 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 460 | super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 461 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; 462 | String tmp = node.toString(); 463 | ClassLoader classLoader = getClass().getClassLoader(); 464 | ImageIcon icon; 465 | if (tmp.startsWith(Kit.sArr)) { 466 | icon = new ImageIcon(classLoader.getResource(baseResPath + "a.gif")); 467 | } else if (tmp.startsWith(Kit.sStr)) { 468 | icon = new ImageIcon(classLoader.getResource(baseResPath + "v.gif")); 469 | } else if (tmp.startsWith(Kit.sObj)) { 470 | icon = new ImageIcon(classLoader.getResource(baseResPath + "o.gif")); 471 | } else if (tmp.startsWith(Kit.sNum)) { 472 | icon = new ImageIcon(classLoader.getResource(baseResPath + "n.gif")); 473 | } else if (tmp.startsWith(Kit.sNull)) { 474 | icon = new ImageIcon(classLoader.getResource(baseResPath + "k.gif")); 475 | } else if (tmp.startsWith(Kit.sBool)) { 476 | icon = new ImageIcon(classLoader.getResource(baseResPath + "v.gif")); 477 | } else { 478 | icon = new ImageIcon(classLoader.getResource(baseResPath + "v.gif")); 479 | } 480 | this.setIcon(icon); 481 | this.setText(tmp.substring(2)); 482 | return this; 483 | } 484 | 485 | }); 486 | } 487 | 488 | private void createTree(Object jsonobj) { 489 | //创建树节点 490 | DefaultMutableTreeNode root = null; 491 | DefaultTreeModel model = null; 492 | try { 493 | JTree tree = getTree(); 494 | System.out.println("Put HashCode : " + tree.hashCode() + " . TabTitle : " + getTabTitle() + " !"); 495 | jsonEleTreeMap.put(tree.hashCode(), jsonobj); 496 | root = Kit.objNode("JSON"); 497 | model = (DefaultTreeModel) tree.getModel(); 498 | // root = (DefaultMutableTreeNode) model.getRoot(); 499 | if (jsonobj instanceof JSONObject) { 500 | analyzeJsonObject((JSONObject) jsonobj, root); 501 | } else if (jsonobj instanceof JSONArray) { 502 | analyzeJsonArray((JSONArray) jsonobj, root, ""); 503 | } 504 | tree.setVisible(true); 505 | model.setRoot(root); 506 | setNodeIcon(tree); 507 | } catch (Exception ex) { 508 | Log.write(ex); 509 | Exceptions.printStackTrace(ex); 510 | showMessageDialog("创建json树失败!", ex.getMessage()); 511 | if (root != null) { 512 | root.removeAllChildren(); 513 | } 514 | if (null != model) { 515 | model.setRoot(root); 516 | } 517 | } 518 | System.gc(); 519 | } 520 | 521 | private JButton createBtnAppTitle(final JTextField textField) { 522 | JButton btnAppTitle = new JButton("标题修改"); 523 | btnAppTitle.addActionListener(new ActionListener() { 524 | @Override 525 | public void actionPerformed(ActionEvent e) { 526 | frame.setTitle(textField.getText()); 527 | } 528 | }); 529 | return btnAppTitle; 530 | } 531 | 532 | private JButton createBtnFormat() { 533 | JButton btnFormat = new JButton("格式化JSON(F)"); 534 | btnFormat.setBackground(new Color(255, 184, 72)); 535 | btnFormat.addActionListener(new ActionListener() { 536 | @Override 537 | public void actionPerformed(ActionEvent e) { 538 | formatJson(); 539 | } 540 | }); 541 | return btnFormat; 542 | } 543 | 544 | private JButton createBtnFormatXml() { 545 | JButton btnFormatXml = new JButton("格式化XML"); 546 | btnFormatXml.setBackground(new Color(3, 98, 253)); 547 | btnFormatXml.addActionListener(new ActionListener() { 548 | @Override 549 | public void actionPerformed(ActionEvent e) { 550 | formatXml(); 551 | } 552 | }); 553 | return btnFormatXml; 554 | } 555 | 556 | private JButton createBtnConvertXml() { 557 | JButton btnConvertXml = new JButton("XML->JSON "); 558 | btnConvertXml.setBackground(Color.YELLOW); 559 | btnConvertXml.addActionListener(new ActionListener() { 560 | @Override 561 | public void actionPerformed(ActionEvent e) { 562 | convertXml(); 563 | } 564 | }); 565 | return btnConvertXml; 566 | } 567 | 568 | private JButton createBtnConvertMap() { 569 | JButton btnConvertMap = new JButton("MAP->JSON "); 570 | btnConvertMap.setBackground(Color.PINK); 571 | btnConvertMap.addActionListener(new ActionListener() { 572 | @Override 573 | public void actionPerformed(ActionEvent e) { 574 | convertMap(); 575 | } 576 | }); 577 | return btnConvertMap; 578 | } 579 | 580 | private JButton createBtnClean() { 581 | JButton btnClean = new JButton("清空(D)"); 582 | btnClean.addActionListener(new ActionListener() { 583 | @Override 584 | public void actionPerformed(ActionEvent e) { 585 | JTextArea ta = getTextArea(); 586 | if (ta != null) { 587 | ta.setText(""); 588 | } 589 | 590 | } 591 | }); 592 | return btnClean; 593 | } 594 | 595 | private JButton createBtnParse() { 596 | JButton btnParse = new JButton("粘帖(V)"); 597 | btnParse.addActionListener(new ActionListener() { 598 | @Override 599 | public void actionPerformed(ActionEvent e) { 600 | JTextArea ta = getTextArea(); 601 | if (ta != null) { 602 | ta.paste(); 603 | //formatJson(); 604 | } 605 | } 606 | }); 607 | return btnParse; 608 | } 609 | 610 | private JButton createBtnNewLine() { 611 | JButton btnNewLine = new JButton("清除(\\n)"); 612 | btnNewLine.addActionListener(new ActionListener() { 613 | @Override 614 | public void actionPerformed(ActionEvent e) { 615 | JTextArea ta = getTextArea(); 616 | if (ta != null) { 617 | ta.setText(ta.getText().replaceAll("\n", "")); 618 | } 619 | } 620 | }); 621 | return btnNewLine; 622 | } 623 | 624 | private JButton createBtnXG() { 625 | JButton btnXG = new JButton("清除(\\)"); 626 | btnXG.addActionListener(new ActionListener() { 627 | @Override 628 | public void actionPerformed(ActionEvent e) { 629 | JTextArea ta = getTextArea(); 630 | if (ta != null) { 631 | ta.setText(ta.getText().replaceAll("\\\\", "")); 632 | } 633 | } 634 | }); 635 | return btnXG; 636 | } 637 | 638 | private JButton createBtnTxtFind() { 639 | JButton btnTxtFind = new JButton("文本查找"); 640 | btnTxtFind.addActionListener(new FindActionListener(frame, tabbedContainer, 1, "文本查找对话框")); 641 | return btnTxtFind; 642 | } 643 | 644 | private JButton createBtnNodeFind() { 645 | JButton btnNodeFind = new JButton("节点查找"); 646 | btnNodeFind.addActionListener(new FindActionListener(frame, tabbedContainer, 2, "树节点查找对话框")); 647 | return btnNodeFind; 648 | } 649 | 650 | private JButton createBtnSelTabName(final JTextField textField) { 651 | JButton btnSelTabName = new JButton("标签名修改"); 652 | btnSelTabName.addActionListener(new ActionListener() { 653 | @Override 654 | public void actionPerformed(ActionEvent e) { 655 | int selIndex = getTabIndex(); 656 | if (selIndex >= 0) { 657 | tabDataModel.setText(selIndex, textField.getText()); 658 | //System.out.println("Modify HashCode : " + getTree(selIndex).hashCode() + " . TabTitle : " + textField.getText() + " !"); 659 | } 660 | } 661 | }); 662 | return btnSelTabName; 663 | } 664 | 665 | private JButton createBtnNewTab() { 666 | JButton btnNewTab = new JButton("新标签(N)"); 667 | btnNewTab.addActionListener(new ActionListener() { 668 | @Override 669 | public void actionPerformed(ActionEvent e) { 670 | addTab("NewTab", true); 671 | } 672 | }); 673 | return btnNewTab; 674 | } 675 | 676 | private JButton createBtnCloseTab() { 677 | JButton btnCloseTab = new JButton("关闭标签"); 678 | btnCloseTab.addActionListener(new ActionListener() { 679 | @Override 680 | public void actionPerformed(ActionEvent e) { 681 | int selIndex = getTabIndex(); 682 | if (selIndex >= 0) { 683 | tabDataModel.removeTab(selIndex); 684 | } 685 | } 686 | }); 687 | return btnCloseTab; 688 | } 689 | 690 | private JToolBar createToolBar() { 691 | JToolBar toolbar = new JToolBar(); 692 | final JTextField textField = new JTextField(); 693 | textField.setMaximumSize(new Dimension(180, 25)); 694 | toolbar.setMargin(new Insets(0, 13, 0, 13)); 695 | toolbar.add(createBtnNewTab()); 696 | toolbar.add(createBtnCloseTab()); 697 | toolbar.add(createBtnFormat()); 698 | toolbar.add(createBtnConvertXml()); 699 | toolbar.add(createBtnConvertMap()); 700 | toolbar.add(createBtnFormatXml()); 701 | toolbar.add(createBtnClean()); 702 | toolbar.add(createBtnParse()); 703 | toolbar.add(createBtnNewLine()); 704 | toolbar.add(createBtnXG()); 705 | toolbar.add(createBtnNodeFind()); 706 | toolbar.add(createBtnTxtFind()); 707 | toolbar.addSeparator(new Dimension(30, 20)); 708 | toolbar.add(textField); 709 | toolbar.add(createBtnAppTitle(textField)); 710 | toolbar.add(createBtnSelTabName(textField)); 711 | return toolbar; 712 | } 713 | 714 | private void convertXml() { 715 | JTextArea ta = getTextArea(); 716 | String text = ta.getText(); 717 | try { 718 | Map map = Kit.xmlToMap(text); 719 | String str = JSON.toJSONString(map, SerializerFeature.WriteMapNullValue); 720 | buildJson(str); 721 | } catch (IOException ex) { 722 | showMessageDialog("转换异常,非法XML字符串!", ex.getMessage()); 723 | } catch (ParserConfigurationException ex) { 724 | showMessageDialog("转换异常,非法XML字符串!", ex.getMessage()); 725 | } catch (SAXException ex) { 726 | showMessageDialog("转换异常,非法XML字符串!", ex.getMessage()); 727 | } 728 | 729 | } 730 | 731 | private void convertMap() { 732 | JTextArea ta = getTextArea(); 733 | String text = ta.getText(); 734 | text = Kit.mapStringToJsonString(text); 735 | buildJson(text); 736 | } 737 | 738 | private void formatXml() { 739 | RSyntaxTextArea ta = getTextArea(); 740 | String xml = ta.getText(); 741 | ta.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML); 742 | try { 743 | xml = Kit.formatXML(xml, true); 744 | ta.setText(xml); 745 | Map json = Kit.xmlToMap(xml); 746 | Object jsonobj = JSON.toJSON(json); 747 | createTree(jsonobj); 748 | } catch (ParserConfigurationException ex) { 749 | showMessageDialog("xml格式化异常", "ParserConfigurationException:\n" + ex.getMessage()); 750 | } catch (SAXException ex) { 751 | showMessageDialog("xml格式化异常", "SAXException:\n" + ex.getMessage()); 752 | } catch (IOException ex) { 753 | showMessageDialog("xml格式化异常IOException", "IOException:\n" + ex.getMessage()); 754 | } catch (DocumentException ex) { 755 | showMessageDialog("xml转换异常Exception", "Exception:\n" + ex.getMessage()); 756 | } 757 | try { 758 | 759 | } catch (Exception e) { 760 | 761 | } 762 | } 763 | 764 | private int addTab(String tabName, boolean isSel) { 765 | TabData tabData = newTabData(tabName, tabName, null); 766 | int newIndex = tabbedContainer.getTabCount(); 767 | tabDataModel.addTab(newIndex, tabData); 768 | if (isSel) { 769 | tabbedContainer.getSelectionModel().setSelectedIndex(newIndex); 770 | } 771 | return newIndex; 772 | } 773 | 774 | public static void main(String args[]) { 775 | try { 776 | javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 777 | } catch (ClassNotFoundException ex) { 778 | java.util.logging.Logger.getLogger(MainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 779 | } catch (InstantiationException ex) { 780 | java.util.logging.Logger.getLogger(MainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 781 | } catch (IllegalAccessException ex) { 782 | java.util.logging.Logger.getLogger(MainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 783 | } catch (UnsupportedLookAndFeelException ex) { 784 | java.util.logging.Logger.getLogger(MainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 785 | } 786 | java.awt.EventQueue.invokeLater(new Runnable() { 787 | @Override 788 | public void run() { 789 | new MainApp().setVisible(true); 790 | } 791 | }); 792 | } 793 | 794 | private void showMessageDialog(String title, String msg) { 795 | if (msg == null) { 796 | msg = ""; 797 | } 798 | JDialog dlg = new JDialog(frame); 799 | dlg.setTitle(title); 800 | dlg.setMinimumSize(new Dimension(350, 160)); 801 | BorderLayout layout = new BorderLayout(); 802 | dlg.getContentPane().setLayout(layout); 803 | dlg.getContentPane().add(new JLabel("异常信息:"), BorderLayout.NORTH); 804 | JTextArea ta = new JTextArea(); 805 | ta.setLineWrap(true); 806 | ta.setText(msg); 807 | ta.setWrapStyleWord(true); 808 | dlg.setLocationRelativeTo(frame); 809 | dlg.getContentPane().add(new JScrollPane(ta), BorderLayout.CENTER); 810 | dlg.setVisible(true); 811 | } 812 | 813 | private void changeLayout() { 814 | int selIndex = getTabIndex(); 815 | if (selIndex < 0) { 816 | return; 817 | } 818 | TabData selTabData = tabDataModel.getTab(selIndex); 819 | JSplitPane splitPane = (JSplitPane) selTabData.getComponent(); 820 | double dividerLocation = 0.6; 821 | if (splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT) { 822 | splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); 823 | splitPane.setDividerLocation(dividerLocation); 824 | } else { 825 | splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); 826 | splitPane.setDividerLocation(dividerLocation); 827 | } 828 | } 829 | 830 | } 831 | --------------------------------------------------------------------------------