效果展示
代码
package com.example.springbootdemo;import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;public class AdvancedJsonViewerGUI extends JFrame {private JTextArea inputTextArea;private JTextArea outputTextArea;private JTree jsonTree;private DefaultTreeModel treeModel;private JButton formatButton;private JButton validateButton;private JButton clearButton;private JButton copyButton;private JButton minifyButton;private JButton sampleButton;private JButton treeViewButton;private JLabel statusLabel;private JCheckBox autoFormatCheckBox;private JTabbedPane outputTabbedPane;private ObjectMapper objectMapper;public AdvancedJsonViewerGUI() {objectMapper = new ObjectMapper();initializeComponents();setupLayout();setupEventHandlers();setupWindow();}private void initializeComponents() {// 输入区域inputTextArea = new JTextArea(15, 50);inputTextArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));inputTextArea.setBorder(new TitledBorder("输入JSON (Input JSON)"));inputTextArea.setLineWrap(true);inputTextArea.setWrapStyleWord(true);// 输出区域 - 文本视图outputTextArea = new JTextArea(15, 50);outputTextArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));outputTextArea.setBorder(new TitledBorder("格式化结果 (Formatted Result)"));outputTextArea.setEditable(false);outputTextArea.setLineWrap(true);outputTextArea.setWrapStyleWord(true);// 输出区域 - 树形视图DefaultMutableTreeNode root = new DefaultMutableTreeNode("JSON");treeModel = new DefaultTreeModel(root);jsonTree = new JTree(treeModel);jsonTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);jsonTree.setShowsRootHandles(true);jsonTree.setEditable(false);jsonTree.setBorder(new TitledBorder("树形视图 (Tree View)"));// 标签页面板outputTabbedPane = new JTabbedPane();outputTabbedPane.addTab("文本视图 (Text View)", new JScrollPane(outputTextArea));outputTabbedPane.addTab("树形视图 (Tree View)", new JScrollPane(jsonTree));// 按钮formatButton = new JButton("格式化 (Format)");validateButton = new JButton("验证 (Validate)");clearButton = new JButton("清空 (Clear)");copyButton = new JButton("复制结果 (Copy)");minifyButton = new JButton("压缩 (Minify)");sampleButton = new JButton("示例 (Sample)");treeViewButton = new JButton("生成树 (Build Tree)");// 复选框autoFormatCheckBox = new JCheckBox("自动格式化 (Auto Format)", false);// 状态标签statusLabel = new JLabel("就绪 (Ready)");statusLabel.setForeground(Color.BLUE);}private void setupLayout() {setLayout(new BorderLayout());// 顶部面板 - 按钮区域JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));topPanel.add(formatButton);topPanel.add(validateButton);topPanel.add(minifyButton);topPanel.add(copyButton);topPanel.add(clearButton);topPanel.add(sampleButton);topPanel.add(treeViewButton);topPanel.add(autoFormatCheckBox);// 中部面板 - 文本区域JPanel textPanel = new JPanel(new GridLayout(1, 2, 10, 0));JPanel inputPanel = new JPanel(new BorderLayout());inputPanel.add(new JScrollPane(inputTextArea), BorderLayout.CENTER);textPanel.add(inputPanel);textPanel.add(outputTabbedPane);// 底部状态栏JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));statusPanel.add(statusLabel);add(topPanel, BorderLayout.NORTH);add(textPanel, BorderLayout.CENTER);add(statusPanel, BorderLayout.SOUTH);}private void setupEventHandlers() {// 格式化按钮formatButton.addActionListener(e -> formatJson());// 验证按钮validateButton.addActionListener(e -> validateJson());// 清空按钮clearButton.addActionListener(e -> clearAll());// 复制按钮copyButton.addActionListener(e -> copyToClipboard());// 压缩按钮minifyButton.addActionListener(e -> minifyJson());// 示例按钮sampleButton.addActionListener(e -> loadSample());// 树形视图按钮treeViewButton.addActionListener(e -> buildTreeView());// 自动格式化autoFormatCheckBox.addActionListener(e -> {if (autoFormatCheckBox.isSelected()) {inputTextArea.addKeyListener(new KeyAdapter() {@Overridepublic void keyReleased(KeyEvent e) {// 延迟执行格式化,避免频繁触发Timer timer = new Timer(500, ev -> formatJson());timer.setRepeats(false);timer.start();}});showStatus("已启用自动格式化", Color.GREEN);}});// 输入区域按键监听inputTextArea.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {// Ctrl+Enter 格式化if (e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) {formatJson();}}});}private void setupWindow() {setTitle("高级JSON查看器 - Advanced JSON Viewer");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);pack();setLocationRelativeTo(null);setResizable(true);setMinimumSize(new Dimension(900, 700));}private void formatJson() {String input = inputTextArea.getText().trim();if (input.isEmpty()) {showStatus("请输入JSON内容", Color.RED);return;}try {JsonNode jsonNode = objectMapper.readTree(input);String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);outputTextArea.setText(formattedJson);showStatus("格式化成功", Color.GREEN);} catch (Exception e) {outputTextArea.setText("错误: 无效的JSON格式\n\n" + e.getMessage());showStatus("格式化失败: " + e.getMessage(), Color.RED);}}private void minifyJson() {String input = inputTextArea.getText().trim();if (input.isEmpty()) {showStatus("请输入JSON内容", Color.RED);return;}try {JsonNode jsonNode = objectMapper.readTree(input);String minifiedJson = objectMapper.writeValueAsString(jsonNode);outputTextArea.setText(minifiedJson);showStatus("压缩成功", Color.GREEN);} catch (Exception e) {outputTextArea.setText("错误: 无效的JSON格式\n\n" + e.getMessage());showStatus("压缩失败: " + e.getMessage(), Color.RED);}}private void validateJson() {String input = inputTextArea.getText().trim();if (input.isEmpty()) {showStatus("请输入JSON内容", Color.RED);return;}try {objectMapper.readTree(input);showStatus("✓ 有效的JSON格式", Color.GREEN);JOptionPane.showMessageDialog(this, "✓ 有效的JSON格式", "验证结果", JOptionPane.INFORMATION_MESSAGE);} catch (Exception e) {showStatus("✗ 无效的JSON格式", Color.RED);JOptionPane.showMessageDialog(this, "✗ 无效的JSON格式:\n" + e.getMessage(), "验证结果", JOptionPane.ERROR_MESSAGE);}}private void copyToClipboard() {String output = outputTextArea.getText();if (!output.isEmpty()) {StringSelection stringSelection = new StringSelection(output);Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();clipboard.setContents(stringSelection, null);showStatus("结果已复制到剪贴板", Color.GREEN);} else {showStatus("没有内容可复制", Color.RED);}}private void clearAll() {inputTextArea.setText("");outputTextArea.setText("");treeModel.setRoot(new DefaultMutableTreeNode("JSON"));showStatus("已清空", Color.BLUE);}private void loadSample() {String sampleJson = "{\n" +" \"name\": \"张三\",\n" +" \"age\": 30,\n" +" \"email\": \"zhangsan@example.com\",\n" +" \"address\": {\n" +" \"street\": \"长安街100号\",\n" +" \"city\": \"北京\",\n" +" \"zipcode\": \"100000\"\n" +" },\n" +" \"skills\": [\"Java\", \"Python\", \"JavaScript\"],\n" +" \"married\": true,\n" +" \"children\": null,\n" +" \"projects\": [\n" +" {\n" +" \"name\": \"项目A\",\n" +" \"duration\": 12,\n" +" \"technologies\": [\"Spring\", \"React\"]\n" +" },\n" +" {\n" +" \"name\": \"项目B\",\n" +" \"duration\": 8,\n" +" \"technologies\": [\"Node.js\", \"Vue.js\"]\n" +" }\n" +" ]\n" +"}";inputTextArea.setText(sampleJson);showStatus("已加载示例数据", Color.BLUE);}private void buildTreeView() {String input = inputTextArea.getText().trim();if (input.isEmpty()) {showStatus("请输入JSON内容", Color.RED);return;}try {JsonNode jsonNode = objectMapper.readTree(input);DefaultMutableTreeNode root = new DefaultMutableTreeNode("JSON");buildTreeNodes(jsonNode, root, "root");treeModel.setRoot(root);outputTabbedPane.setSelectedIndex(1); // 切换到树形视图showStatus("树形视图构建成功", Color.GREEN);} catch (Exception e) {showStatus("构建树形视图失败: " + e.getMessage(), Color.RED);}}private void buildTreeNodes(JsonNode jsonNode, DefaultMutableTreeNode parent, String fieldName) {if (jsonNode.isObject()) {DefaultMutableTreeNode objectNode = new DefaultMutableTreeNode(fieldName + " (Object)");parent.add(objectNode);jsonNode.fields().forEachRemaining(entry -> {String key = entry.getKey();JsonNode value = entry.getValue();buildTreeNodes(value, objectNode, key);});} else if (jsonNode.isArray()) {DefaultMutableTreeNode arrayNode = new DefaultMutableTreeNode(fieldName + " (Array[" + jsonNode.size() + "])");parent.add(arrayNode);for (int i = 0; i < jsonNode.size(); i++) {JsonNode element = jsonNode.get(i);buildTreeNodes(element, arrayNode, "[" + i + "]");}} else {String valueStr = jsonNode.asText();if (jsonNode.isNull()) {valueStr = "null";} else if (jsonNode.isNumber()) {valueStr = jsonNode.asText();} else if (jsonNode.isBoolean()) {valueStr = String.valueOf(jsonNode.asBoolean());} else {valueStr = "\"" + valueStr + "\"";}parent.add(new DefaultMutableTreeNode(fieldName + ": " + valueStr));}}private void showStatus(String message, Color color) {statusLabel.setText(message);statusLabel.setForeground(color);}public static void main(String[] args) {try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch (Exception e) {e.printStackTrace();}SwingUtilities.invokeLater(() -> {new AdvancedJsonViewerGUI().setVisible(true);});}
}