美文网首页
JSON工具类的构建(后端版本)

JSON工具类的构建(后端版本)

作者: cartoony | 来源:发表于2019-10-05 20:09 被阅读0次

    前言

    在前后端交互的选择上,之前一直采用的是模板引擎(因为我只负责后端)。
    而这次的一个算是作业吧,前后端都是我,所以就研究了一下JSON交互在java web的应用(主要是前端)。

    优缺点

    • 前后端耦合

      • 模板引擎加载只是将jsp的交互方式移植到html上,前端文件格式改变了,但是jsp中前后端耦合的缺点没有改变。
      • json交互中,数据通过js/jquery动态加载在页面上,数据与页面进行分离,页面只是单纯用于展示。
    • 数据加载逻辑复用

      • 模板引擎的方式中,如果有很多相似的页面元素以及一样的数据返回格式,那只是复制粘贴大法了。
      • 在模板引擎的例子中,只需要定义一套数据加载模型,传入不同的页面元素id以及数据则能实现逻辑复用
    • 后端接口的复用
      因为我的学习路线的问题,所以我开发过安卓原生一段时间。

      • 模板引擎式的加载必须使用webView组件加载,且需另进行原生构建时接口也要另外构建。
      • json交互,谷歌爸爸鼓励使用json进行交互(一年多前的事,现在不清楚了),且安卓原生内置GJSON进行json解析与构建,所以可以在原生以及跨平台的构建有很好的平衡。

    对比

    既然选择了json交互的方式,而java官方据我所知是没有内置对json的支持,Spring在Controller的层面使用RestContrller注解实现对json的支持。
    但是我个人强迫症很强,我对Contrller(或者说是Presenter)的定义是

    • 对用户访问的url作页面的映射
    • 对用户触发的事件进行数据的传递与返回
      正是这两点的定义,我需要在Service层组合统一格式的结果返回到上层,所以需要第三方json支持。
      可选择的JSON库有很多,GSON,FastJson,Jackson,根据对比,我选择为马老师充值一波。

    需求拆分

    我初步定义的需求主要有三个

    • Service传递统一处理结果到上层
    • 无论是单一数据实体或者List型数据处理的结果是一样的
    • 处理过程是独立的,不依赖于实体类的支持

    格式设计

    在网上看过很多后端返回数据的格式,很多都是返回一个处理的status以及具体的数据,而这个status是根据http状态码进行设定的,因为这次时间比较紧,所以我就采用了这个方案。

    {
        "status": "status",
        "object": {
            
        }
    }
    

    代码设计

    因为我希望Controller能直接拿到结果,所以构建结果的过程全放在Result类中。
    而结果构建我主要分为两种:只有状态码(通知处理结果)以及具有返回结果(数据显示),而根据结果的个人也分为两种:单个数据以及List型数据。

    实际代码

    @Getter
    @Slf4j
    public class ResultSet {
    
        private JSONObject result;
    
        public ResultSet(){
            result=new JSONObject();
        }
    
        /**
         * 初始化状态码
         * @param status
         */
        public void initStatus(String status){
            result.put("status", status);
        }
    
        /**
         * 初始化状态码以及返回数据
         * @param status
         * @param obj
         */
        public void initData(String status,Object obj){
            initStatus(status);
            if(obj instanceof List){
                List list=(List)obj;
                JSONArray array=new JSONArray();
                for(Object object:list){
                    array.add(putObjectToJSON(object));
                }
                result.put("object",array);
            }
            else {
                result.put("object",putObjectToJSON(obj));
            }
        }
    
        /**
         * 将单个Object放入json文件中
         * @param obj
         * @return
         */
        private JSONObject putObjectToJSON(Object obj){
            JSONObject result=new JSONObject();
            Field[] fields=obj.getClass().getDeclaredFields();
            for(Field field:fields){
                field.setAccessible(true);
                String fieldName=field.getType().getSimpleName();
                if(fieldName.equals("Department")||fieldName.equals("Job")){
                    JSONObject tempJson=new JSONObject();
                    try {
                        Object tempObject = field.get(obj);
                        Field[] tempFields=tempObject.getClass().getDeclaredFields();
                        for(Field tempField:tempFields){
                            tempField.setAccessible(true);
                            tempJson.put(tempField.getName(),tempField.get(tempObject));
                            tempField.setAccessible(false);
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    if(fieldName.equals("Department")){
                        result.put("depart",tempJson);
                    }
                    else {
                        result.put("job",tempJson);
                    }
                }
                else {
                    try {
                        result.put(field.getName(),field.get(obj));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                field.setAccessible(false);
            }
            return result;
        }
    }
    

    代码思路

    1. Service通过initStatus/initData传入数据/状态码进行对象的生成

    2. Controller通过result的getter方法获取处理结果

    3. 单个数据以及List数据的处理

      1. 单个对象直接通过putObjectToJSON进行处理
      2. List数据通过对象类型判断,向下转型,遍历元素形成JSONArray进行处理,对元素处理的方法也是采用putObjectToJSON
    4. 嵌套对象的处理

      public class Employee {
      
         private int id;
      
         private Department depart;
      
         private Job job;
      
         private String name;
      
          ..................
      }
      
      1. 通过反射获取对象的所有成员变量类型以及对应的值
      2. 遇到上述bean类含有嵌套自定义对象时,递归生成json文件加入到结果json中

    结果演示

    image

    ​ (左为单object型,右为List型)

    不足之处

    1. 状态码的设置应该采用枚举类的赋值,能更好的约束返回的状态码
    2. 在对象转换方面,应该采用配置扫描的方式。在配置文件中写入bean的包所在,在嵌套对象转换时通过扫描配置文件的信息判断
    3. 在嵌套对象的转换方面,只是做了一层的嵌套转换,更多层的没有考虑到,之后会再重构的
    4. 对异常处理方面,只是简单的输出错误信息。应该对错误信息进行进一步的处理

    后记

    因为这次时间比较赶,从项目的立项到成品的建立花了5天时间,所以注意到很多细节,但是没有去处理。
    有想过之后有时间的话将这个工具类的细节完善起来,形成jar包供自己或者供开源。

    相关连接

    这只是后台对结果的统一处理,我另外写了一篇文章:JSON工具类的构建(前端版本),配合使用效果更佳哦~

    本文首发于cartoon的博客
    转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/json/json工具类的构建后端版本/

    相关文章

      网友评论

          本文标题:JSON工具类的构建(后端版本)

          本文链接:https://www.haomeiwen.com/subject/itjypctx.html