图形化数据报文转换映射工具

发布于:2025-02-10 ⋅ 阅读:(43) ⋅ 点赞:(0)

概要

在当今数字化时代,数据的处理和分析是企业、科研机构以及各类组织日常运营的核心环节。数据来源广泛,格式多样,常见的数据格式包括XML(可扩展标记语言)和JSON(JavaScript对象表示法)。XML以其结构化和可扩展性强的特点,被广泛应用于配置文件、数据交换以及复杂数据结构的描述;而JSON则因其简洁、易读易解析的特性,在Web开发、API接口以及轻量级数据传输中占据重要地位。然而,在实际的数据处理流程中,我们经常会遇到需要将一种数据格式转换为另一种格式的情况,以满足不同系统、平台或应用之间的数据交互需求。

具体来说,常见的数据映射转换需求包括以下几种场景:

  1. XML到XML的转换:当数据在不同的XML系统之间传递时,可能需要对数据结构进行调整或优化,以适配目标系统的XML模式。例如,将一个复杂的企业级配置文件从一种XML格式转换为另一种更简洁或更符合规范的XML格式,以提高系统的兼容性和可维护性。
  2. JSON到JSON的转换:在Web开发和数据处理中,JSON数据结构可能需要根据不同的应用场景进行调整。比如,将一个包含大量嵌套对象和数组的JSON数据重新组织,以便更好地适配前端展示或后端处理逻辑。这种转换可能涉及字段的重命名、数据类型的转换以及数据结构的重组。
  3. XML到JSON的转换:随着Web技术的发展,越来越多的系统倾向于使用JSON作为数据传输格式。因此,当从一个基于XML的旧系统迁移到一个基于JSON的新系统时,就需要将XML数据转换为JSON格式。例如,将一个XML格式的用户配置文件转换为JSON格式,以便在现代的Web应用中使用。
  4. JSON到XML的转换:在某些情况下,尽管JSON是主流的数据格式,但某些系统或平台可能仍然依赖XML。例如,将JSON格式的API响应数据转换为XML格式,以适配遗留系统的数据处理需求。

为了高效、准确地完成这些数据格式的转换和映射,我们需要一个灵活且强大的工具或框架。

通过实现这样一个数据格式转换工具,我们不仅可以提高数据处理的效率,还能确保数据在不同系统之间的顺畅交互,从而为企业的数字化转型和数据驱动的决策提供有力支持。

在当前的数据处理领域,虽然有许多数据映射和转换工具可供选择,但很难找到一款完全符合个性化需求的工具。为此,我们开发了一款基于Java的数据转换映射工具,旨在提供一种直观、高效且易于操作的解决方案。该工具的图形界面基于Swing开发,支持XML和JSON两种常见数据格式的转换。

工具功能特点

  1. 支持多种数据格式
    用户可以选择XML和JSON作为源格式和目标格式,工具支持从XML到XML、XML到JSON、JSON到XML以及JSON到JSON的双向转换。
  2. 树形结构可视化
    数据加载后会以树形格式展示,用户可以清晰地查看数据结构。这种可视化方式使得数据映射过程更加直观。
  3. 拖拽式映射操作
    用户可以通过拖动源树的节点到目标树的节点,形成连线完成数据映射。这种拖拽式操作极大地简化了映射过程,降低了操作难度。
  4. 灵活的映射规则配置
    支持基于规则的映射和条件映射,用户可以根据实际需求自定义映射逻辑。

通过Swing开发的图形界面,用户可以轻松上手操作,无需复杂的配置和编程知识。这种无代码或低代码的映射方式,使得工具不仅适用于开发人员,也适合非技术背景的用户。

整体架构流程

经过长时间的钻研分析相关技术,通过实现可视化界面映射,使用Dom4j和fastjson进行xml和json的数据处理,制定了连线的映射规则,形成了一个能够在xml和json之间任意节点进行映射转换的工具。

实现工具的界面如下:

界面上的菜单中能够选择源和目标,将数据加载成树型。

界面上能够拖拽进行连线映射。

可选择菜单中的保存来保存映射连线

可通过菜单中的执行按钮进行数据映射测试

技术细节

    1. 界面实现

界面采用swing开发,不熟悉swing的同学可先学习一下swing的相关知识。代码较多这里只给出部分关键代码。

主题界面代码如下:

/**

        *

        * 构造函数

        */

       public Transformer() {

              super("数据映射");//标题

              instance = this;

              XMLMapperInit.initLookAndFeel();

              setIconImage(XMLMapperInit.loadIcon(XMLMapperInit.ICON_APP).getImage());

              mapView = new MapView(this);//映射区

              outputXSLT = new JTextArea();

              testMessageView = new XmlPane();

              testMessageView.setContentType("text/xml");

              tabPane = new MyTabbedPane();

              getContentPane().add(tabPane);

              menuBar = new MyMenuBar();//菜单

              setJMenuBar(menuBar);

       }

这里主要看映射区,在这里创建了左右的两棵树,并生成了中间的连线面板来显示连线。

/**

        *

        * 构造函数

        *

        * @param transformer

        *            界面类

        */

       public MapView(Transformer transformer) {

              super(JSplitPane.VERTICAL_SPLIT, true);

              this.transformer = transformer;

              srcTree = new MapperTree(false);

              dstTree = new MapperTree(true);

              /**

               * 设置两棵树的ComponentModel属性,树丛该属性中获得消息格式的值

               *

               * @author mzj

               */

              srcTree.setComponentModel(transformer.getSourceModel());

              dstTree.setComponentModel(transformer.getDestinationModel());

              objectPanel = new ObjectPanel(this, srcTree, dstTree);

              propView = new PropertyPane(this);

              leftPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);

              rightPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);

              srcTree.addTreeSelectionListener(propView);

              dstTree.addTreeSelectionListener(propView);

              leftPane.setBorder(null);

              rightPane.setBorder(null);

              this.setBorder(null);

              // ///

              // Positioning the main components between the splitters

              // ///

              leftPane.setLeftComponent(srcTree.getScrollPane());

              leftPane.setRightComponent(rightPane);

              rightPane.setLeftComponent(objectPanel);

              rightPane.setRightComponent(dstTree.getScrollPane());

              this.setTopComponent(leftPane);

              // this.setBottomComponent(propView);

              leftPane.setDividerSize(2);

              rightPane.setDividerSize(2);

              addComponentListener(new ComponentListener() {

                     public void componentHidden(ComponentEvent e) {

                     }

                     public void componentMoved(ComponentEvent e) {

                     }

                     public void componentResized(ComponentEvent e) {

                            Dimension d = e.getComponent().getSize();

                            setSize(d);

                            int x = getWidth() / 3;

                            rightPane.setDividerLocation(x);

                            leftPane.setDividerLocation(x);

                            MapView.this.setDividerLocation((int) ((getHeight() / 3) * 2));

                     }

                     public void componentShown(ComponentEvent e) {

                     }

              });

       }

    1. 源和目标的数据加载

通过选择文件菜单中的加载源和加载目标进行数据格式加载。相关代码如下:

public void loadOutFileXML(String dirOne) throws DocumentException {

              String messageXml = dirOne;

              if(dirOne.endsWith(".json")) {

                     sourceType=NodeUtil.JSON;

              }else {

                     sourceType=NodeUtil.XML;

              }

              if (messageXml != null && !messageXml.equals("")) {

                     MapperTree.this.load(dirOne);

              }

       }

       public void loadInFileXML(String dirTwo) throws DocumentException {

              String messageXml = dirTwo;

              if(dirTwo.endsWith(".json")) {

                     targetType=NodeUtil.JSON;

              }else {

                     targetType=NodeUtil.XML;

              }

             

              if (messageXml != null && !messageXml.equals("")) {

                     MapperTree.this.load(dirTwo);

              }

       }

将数据加载成MapperTreeModel加载到界面上显示,MapperTreeModel类继承了DefaultTreeModel。

public class MapperTreeModel extends DefaultTreeModel {

       private static final long serialVersionUID = 6124199500486839241L;

       protected boolean bLoaded = false;

       /**

        * @author mzj

        */

       private GeneriqueSpoModel componentModel;

       public MapperTreeModel(MapperTreeNode newRoot) {

              super(newRoot);

       }

       public boolean Load(String filename) {

              return false;

       }

       public boolean isLoaded() {

              return bLoaded;

       }

       /**

        * @param componentModel

        */

       public void setComponentModel(GeneriqueSpoModel componentModel) {

              this.componentModel = componentModel;

       }

       /**

        * @return

        */

       public GeneriqueSpoModel getComponentModel() {

              return componentModel;

       }

}

    1. 映射界面

这里MapperTree继承了JTree实现了可拖拽的树。ObjectPanel实现了JPanel面板。用于绘制拖拽的连线。ObjectPanel实现了画线的事件。

class MyDragSourceListener implements DragSourceListener {

              public void dragDropEnd(DragSourceDropEvent event) {

                     if (event.getDropSuccess()) {

                            repaint(); // 画线

                     }

              }

              public void dragEnter(DragSourceDragEvent event) {

                     DragSourceContext context = event.getDragSourceContext();

                     context.setCursor(DragSource.DefaultLinkDrop);

              }

              public void dragExit(DragSourceEvent event) {

              }

              public void dragOver(DragSourceDragEvent event) {

              }

              public void dropActionChanged(DragSourceDragEvent event) {

              }

       }

      

       class MyDragGestureListener implements DragGestureListener {

              public void dragGestureRecognized(DragGestureEvent event) {

                     Point pt = event.getDragOrigin();

                     IMapObject obj = ObjectPanel.this.getMap().getChildAt(pt);

                     if (obj != null && (obj instanceof ILinkable)) {

                            ILinkable src = (ILinkable) obj;

                            if (src.willAccept(null)) {

                                   dragSource.startDrag(event, DragSource.DefaultLinkDrop,

                                                 (Transferable) src, new MyDragSourceListener());

                                   setDragLine(src, new DefaultLinkable(pt));

                                   repaint();

                                   return;

                            }

                     }

              }

       }

      

       class MyDropTargetListener implements DropTargetListener {

              public void dragEnter(DropTargetDragEvent event) {

              }

              public void dragExit(DropTargetEvent event) {

                     bDragLine = false;

                     repaint();

              }

              public void dragOver(DropTargetDragEvent event) {

                     if (!event

                                   .isDataFlavorSupported(MapperTreeNode.mapperTreeNodeFlavor)

                                   && !event

                                                 .isDataFlavorSupported(DefaultLinkable.linkableFlavor)

                                   && !event

                                                 .isDataFlavorSupported(DefaultLinkable.localLinkableFlavor)) {

                            return;

                     }

                     Point pt = event.getLocation();

                     Transferable t = event.getTransferable(); // JDK 1.5

                     ILinkable src = DefaultLinkable.getLinkable(t);

                     ILinkable dst = new DefaultLinkable(pt);

                     IMapObject obj = ObjectPanel.this.getMap().getChildAt(pt);

                     if (obj != null && (obj instanceof ILinkable))

                            dst = (ILinkable) obj;

                     if (dst.willAccept(src)) {

                            dragLine = new LinkLine(src, dst);

                            bDragLine = true;

                            ObjectPanel.this.repaint();

                     }

              }

              public void drop(DropTargetDropEvent event) {

                     Transferable t = event.getTransferable();

                     ILinkable src = DefaultLinkable.getLinkable(t);

                     Point pt = event.getLocation();

                     IMapObject dst = ObjectPanel.this.getMap().getChildAt(pt);

                     if (dst != null && (dst instanceof ILinkable))

                            if (((ILinkable) dst).willAccept(src))

                                   addLink(src, (ILinkable) dst);

                     map.repaint();

              }

              public void dropActionChanged(DropTargetDragEvent event) {

              }

       }

      

       class MyMouseListener implements MouseListener {

              public void mouseClicked(MouseEvent e) {

              }

              public void mouseEntered(MouseEvent e) {

              }

              public void mouseExited(MouseEvent e) {

              }

              public void mousePressed(MouseEvent e) {

                     IMapObject obj = ObjectPanel.this.getMap().getChildAt(e.getPoint());

                     if (null != obj)

                            objectSelected(obj);

                     else

                            objectSelected(map);

              }

              public void mouseReleased(MouseEvent e) {

                     if (e.isPopupTrigger()) {

                            ptPopup = e.getPoint();

                            IMapObject obj = ObjectPanel.this.getMap().getChildAt(ptPopup);

                            JPopupMenu popup = new MyPopupMenu(obj);

                            popup.show(e.getComponent(), e.getX(), e.getY());

                            ObjectPanel.this.repaint();

                     }

              }

       }

鼠标事件用于设置连线的属性,可在连线上创建函数,用于数据处理。

    1. 连线定义

绘制连线的时候需要进行连线的属性定义。

import java.util.ArrayList;

import java.util.List;

/**

 * 连线属性

 * @author song0

 *

 */

public class lineMapping {

      

       private String id;//连线ID

      

       private String parentId;//父级连线ID

      

       private List<String> childNodeId;//子连线ID集合

      

       private String sourceNode;//源xpath或jpath 含有@代表属性 没有@代表节点

      

       private String targetNode;//目标xpath或jpath 含有@代表属性 没有@代表节点

      

       private String lineType;//点对点one,循环for

      

       private String sourceType;//xml,json

      

       private String targetType;//xml,json

      

       private List<String> function;//函数列表

      

       public lineMapping() {

              childNodeId=new ArrayList<String>();

              function=new ArrayList<String>();

       }

       public String getSourceNode() {

              return sourceNode;

       }

       public void setSourceNode(String sourceNode) {

              this.sourceNode = sourceNode;

       }

       public String getTargetNode() {

              return targetNode;

       }

       public void setTargetNode(String targetNode) {

              this.targetNode = targetNode;

       }

       public String getLineType() {

              return lineType;

       }

       public void setLineType(String lineType) {

              this.lineType = lineType;

       }

       public String getSourceType() {

              return sourceType;

       }

       public void setSourceType(String sourceType) {

              this.sourceType = sourceType;

       }

       public String getTargetType() {

              return targetType;

       }

       public void setTargetType(String targetType) {

              this.targetType = targetType;

       }

       public List<String> getFunction() {

              return function;

       }

       public void setFunction(List<String> function) {

              this.function = function;

       }

      

       public void addFunction(String function) {

              this.function.add(function);

       }

      

       public String getFunction(int index) {

              return this.function.get(index);

       }

       public String getId() {

              return id;


网站公告

今日签到

点亮在社区的每一天
去签到