Map数据验证

背景: 当用Map list 嵌套为数据配置时,存在一个数据验证问题。本文原创,没有深度测试

 

代码:

import com.fyh.utils.mapt.Mapt;

import java.util.*;
import java.util.stream.Collectors;

public class BValidt {
    private String nameSpace;
    private String separator = "\\.";
    private boolean friendsKeyBL = false;

    /**
     * 对由List,map进行嵌套的对象进行数据检验,本质是他们与json相对应。
     *
     * @param ds
     * @param std
     * @return code =1,成功; code =0,失败
     */
    public Map<String, Object> validByPath(Object ds, Map<String, String> std, boolean isStdValid) {

        Map<String, Object> rst = new LinkedHashMap<>();
        rst.put("code", 1);
        if (std == null) {
            return rst;
        } else if (std != null && ds == null) {
            rst.put("code", 0);
            return rst;
        }

        Map<String, String> resultMap = new LinkedHashMap<>();
        rst.put("result", resultMap);

        Map<String, String> ruleMap = null;
        if (isStdValid) {
            ruleMap = new LinkedHashMap<>();
            for (Map.Entry<String, String> kv : std.entrySet()) {
                String ruleStr = kv.getKey().trim();
                Map<String, String> tmpPathMap = getPaths(ds, ruleStr);
                for (String tmpstr : tmpPathMap.keySet()) {
                    ruleMap.put(tmpstr, kv.getValue());
                }
            }
        } else {
            ruleMap = std;
        }

        for (Map.Entry<String, String> kv : ruleMap.entrySet()) {
            Object dsObj = Mapt.get(ds, kv.getKey());
            String ruleStr = kv.getKey().trim();
            Entity rstEntity = doValid(dsObj, kv.getValue());
            resultMap = doReturn(resultMap, ruleStr, rstEntity);
        }
        resultMap=resultMap.entrySet().stream()
                .sorted( Map.Entry.comparingByKey())
                .collect(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (oldVal, newVal) -> oldVal,
                                LinkedHashMap::new
                        )
                );

        return rst;

    }

    private Map<String, String> getPaths(Object ds, String ruleStr) {
        Map<String, String> pathMap = new LinkedHashMap<>();//只存储对数组计算的规则的路径
        if (ds == null || ruleStr == null) return pathMap;

        if (friendsKeyBL) {
            ruleStr = ruleStr.replaceAll("(?<=[A-Z|a-z|0-9|\\]])(\\[)", ".[");
        }
        String[] strs = ruleStr.split(separator);
        String prePath = "";
        for (String str : strs) {
            if (str.substring(0, 1).equals("[")) {
                pathMap.put(prePath, "0");
                List tmpList = null;
                if (prePath.equals("") && List.class.isAssignableFrom(ds.getClass())) {
                    tmpList = (List) ds;
                } else {
                    tmpList = Mapt.getList(ds, prePath);
                }
                int count = tmpList.size();
                Map<String, String> newPathMap = new LinkedHashMap<>();
                for (int i = 0; i < count; i++) {
                    for (String k : pathMap.keySet()) {
                        String tmpStr = "[" + Integer.toString(i) + "]";
                        if (k.equals("")) {
                            newPathMap.put(tmpStr, "0");
                        } else {
                            newPathMap.put(k + "." + tmpStr, "0");
                        }
                    }
                }

                pathMap = newPathMap;

            } else if (pathMap.isEmpty()) {
                prePath = prePath.equals("") ? str : prePath + "." + str;
            } else {
                Map<String, String> newPathMap = new LinkedHashMap<>();
                for (String k : pathMap.keySet()) {
                    String tmpstr = k.equals("") ? str : k + "." + str;
                    newPathMap.put(tmpstr, "0");
                }
                pathMap = newPathMap;
            }
        }
        if (pathMap.isEmpty()) pathMap.put(ruleStr, "0");
        return pathMap;
    }

    private Map<String, String> doReturn(Map<String, String> resultMap, String key, Entity rstEntity) {
        if (rstEntity == null) return resultMap;
        if (rstEntity.rst && rstEntity.sonRst != null) {
            resultMap.put(key, rstEntity.sonRst.toString());
        }
        return resultMap;
    }

    /**
     * 对由List,map进行嵌套的对象进行数据检验,本质是他们与json相对应。
     *
     * @param ds  被验证的数据源,由List,map进行嵌套嵌套构
     * @param std 由由List,map进行嵌套构成的验证规则
     * @return code =1,成功; code =0,失败
     */
    public Map<String, Object> valid(Object ds, Object std) {

        Map<String, Object> rst = new LinkedHashMap<>();
        rst.put("code", 1);
        if (std == null) {
            return rst;
        } else if (std != null && ds == null) {
            rst.put("code", 0);
            return rst;
        }

        Queue<Object> stdQueue = new LinkedList<>();
        stdQueue.offer(std);
        Queue<Object> dsQueue = new LinkedList<>();
        dsQueue.offer(ds);
        Queue<Object> rstQueue = new LinkedList<>();
        if (List.class.isAssignableFrom(ds.getClass())) {
            List list = new ArrayList();
            rst.put("result", list);
            rstQueue.offer(list);
        } else if (Map.class.isAssignableFrom(ds.getClass())) {
            Map<String, Object> map = new LinkedHashMap<>();
            rst.put("result", map);
            rstQueue.offer(map);
        }
        while (!dsQueue.isEmpty()) {
            Object stdObj = stdQueue.poll();
            Object dsObj = dsQueue.poll();
            Object rstObj = rstQueue.poll();
            if (stdObj == null) break;
            if (List.class.isAssignableFrom(dsObj.getClass())
                    && List.class.isAssignableFrom(stdObj.getClass())
            ) {

                List dsList = (List) dsObj;
                List stdList = (List) stdObj;
                List rstList = (List) rstObj;
                Object sunStdObj = stdList.get(0);
                for (int i = 0; i < dsList.size(); i++) {
                    Object son = dsList.get(i);
                    Entity rstEntity = doValid(son, sunStdObj); //开始验证
                    if (rstEntity.rst) {
                        if (rstEntity.sonRst != null) {
                            rst.put("code", 0);
                            rstList.add(rstEntity.sonRst);
                        }
                    } else if (List.class.isAssignableFrom(son.getClass())) {
                        List tmpList = new ArrayList<>();
                        rstList.add(tmpList);
                        dsQueue.offer(son);
                        if (i < stdList.size()) {
                            stdQueue.offer(stdList.get(i));
                        } else {
                            stdQueue.offer(stdList.get(0));
                        }
                        rstQueue.offer(tmpList);
                    } else if (Map.class.isAssignableFrom(son.getClass())) {
                        Map<String, Object> tmpMap = new LinkedHashMap<>();
                        rstList.add(tmpMap);
                        dsQueue.offer(son);
                        if (i < stdList.size()) {
                            stdQueue.offer(stdList.get(i));
                        } else {
                            stdQueue.offer(stdList.get(0));
                        }

                        rstQueue.offer(tmpMap);
                    }
                }
            } else if (Map.class.isAssignableFrom(dsObj.getClass())
                    && Map.class.isAssignableFrom(stdObj.getClass())
            ) {
                Map<String, Object> dsMap = (Map<String, Object>) dsObj;
                Map<String, Object> stdMap = (Map<String, Object>) stdObj;
                Map<String, Object> rstMap = (Map<String, Object>) rstObj;
                for (Map.Entry<String, Object> en1 : dsMap.entrySet()) {
                    Object son = en1.getValue();
                    Object sunStdObj = stdMap.get(en1.getKey());
                    Entity rstEntity = doValid(son, sunStdObj);//开始验证
                    if (rstEntity.rst) {
                        if (rstEntity.sonRst != null) {
                            rst.put("code", 0);
                            rstMap.put(en1.getKey(), rstEntity.sonRst);
                        }
                    } else if (List.class.isAssignableFrom(son.getClass())) {
                        List tmpList = new ArrayList<>();
                        rstMap.put(en1.getKey(), tmpList);
                        dsQueue.offer(son);
                        stdQueue.offer(stdMap.get(en1.getKey()));
                        rstQueue.offer(tmpList);
                    } else if (Map.class.isAssignableFrom(son.getClass())) {
                        Map<String, Object> tmpMap = new LinkedHashMap<>();
                        rstMap.put(en1.getKey(), tmpMap);
                        dsQueue.offer(son);
                        stdQueue.offer(stdMap.get(en1.getKey()));
                        rstQueue.offer(tmpMap);
                    }
                }
            }
        }

        return rst;
    }

    /**
     * @param son
     * @param sonStdObj
     * @return Entity.rst 为false-没到底,需要进步处理,true--已经到底并检验了
     */
    private Entity doValid(Object son, Object sonStdObj) {
        Entity rst = new Entity(son, sonStdObj);
        if (son == null || sonStdObj == null) {
            rst.rst = true;
            return rst;
        }
        if (String.class.isAssignableFrom(sonStdObj.getClass())) {
            rst.rst = true;
            // "aa;dd;xx;;;yy".split(";(?!;)") 分割符为分号,如果有连续分号,只有最后一个分号会分割
            String[] strs = sonStdObj.toString().split(";(?!;)");
            String[] params = Arrays.copyOfRange(strs, 1, strs.length - 1);
            int lastIndex = strs.length - 1;
            if (strs[0].toLowerCase().equals("type") && strs[1] == null) {
                rst.sonRst = "验证类型出错";
                if (rst.sonRst != null) rst.sonRst = rst.sonRst + ". 原值为:" + son.toString();
            } else if (strs[0].toLowerCase().equals("type") && strs[1] != null) {
                strs[1] = strs[1].trim();
                try {
                    if (!strs[1].contains("java.lang") && (
                            strs[1].equals("String") || strs[1].equals("Integer") ||
                                    strs[1].equals("Boolean") || strs[1].equals("String") ||
                                    strs[1].equals("Double") || strs[1].equals("Long") ||
                                    strs[1].equals("String")
                    )
                    ) {
                        strs[1] = "java.lang." + strs[1];
                    }
                    if (strs[1].equals("Date")) {
                        strs[1] = "java.util.Date";
                    }

                    if (this.nameSpace != null && !strs[1].contains(".")) {
                        strs[1] = this.nameSpace + "." + strs[1];
                    }
                    Class cls = Class.forName(strs[1]);
                    if (cls.isAssignableFrom(son.getClass())) {
                        return rst;
                    } else {
                        rst.sonRst = strs[2] != null ? strs[2] : "不是指定类型";
                        if (rst.sonRst != null) rst.sonRst = rst.sonRst + ". 原值为:" + son.toString();
                    }
                } catch (ClassNotFoundException e) {
                    rst.sonRst = strs[2] != null ? strs[2] : "验证类型出错";
                    if (rst.sonRst != null) rst.sonRst = rst.sonRst + ". 原值为:" + son.toString();
                    return rst;
                }

            }
            if (Validt.valid(strs[0], son.toString(), params)) {
                return rst;
            } else {
                rst.sonRst = strs[lastIndex] != null ? strs[lastIndex] : "验证" + strs[0] + "出错";
                if (rst.sonRst != null) rst.sonRst = rst.sonRst + ". 原值为:" + son.toString();
                return rst;
            }


        }
        return rst;
    }


    public String getNameSpace() {
        return nameSpace;
    }

    public void setNameSpace(String nameSpace) {
        this.nameSpace = nameSpace;
    }

    class Entity {
        protected boolean rst = false;
        protected Object son;
        protected Object sonRst;
        protected Object sonStdObj;

        public Entity() {
        }

        public Entity(Object son, Object sonStdObj) {
            this.son = son;
            this.sonStdObj = sonStdObj;
        }

        public boolean isRst() {
            return rst;
        }

        public void setRst(boolean rst) {
            this.rst = rst;
        }

        public Object getSon() {
            return son;
        }

        public void setSon(Object son) {
            this.son = son;
        }

        public Object getSonStdObj() {
            return sonStdObj;
        }

        public void setSonStdObj(Object sonStdObj) {
            this.sonStdObj = sonStdObj;
        }


        public Object getSonRst() {
            return sonRst;
        }

        public void setSonRst(Object sonRst) {
            this.sonRst = sonRst;
        }
    }


}

 

 

测试与使用

 

  1 import com.fyh.utils.JackJsonUtils;
  2 import org.junit.jupiter.api.Test;
  3 
  4 import java.util.*;
  5 
  6 import static org.junit.jupiter.api.Assertions.*;
  7 
  8 class BValidtTest {
  9     private BValidt bValidt = new BValidt();
 10     @Test
 11     void validByPath(){
 12         Arrays.asList("a", "b", "c").forEach(i->{System.out.println(i);});
 13         Arrays.asList("a", "b", "c").forEach(System.out::println);
 14 
 15         String dsStr = JackJsonUtils.getStdJsonStr("{no:1,name:'a'}");
 16         Map<String, Object> dsMap = JackJsonUtils.fromJson(dsStr, Map.class);
 17 
 18         Map<String,String> ruleMap=new LinkedHashMap<>();
 19         ruleMap.put("no","num;3;不是数或小数位数出错");
 20         ruleMap.put("name","required; 不能为空");
 21         Map<String, Object> rst = bValidt.validByPath(dsMap, ruleMap,true);
 22 
 23         List<Map<String,Object>> dsList=new ArrayList<>() ;
 24         Map<String,Object> dsMapA=new LinkedHashMap<>();
 25         dsList.add(dsMapA);
 26         dsMapA.put("no","11");
 27         dsMapA.put("name","");
 28         dsMapA=new LinkedHashMap<>();
 29         dsList.add(dsMapA);
 30         dsMapA.put("no","22");
 31         dsMapA.put("name","");
 32 
 33 
 34         Map<String,String> stdMapA=new LinkedHashMap<>();
 35         stdMapA.put("[0].no","num;3;不是指定类型");
 36         stdMapA.put("[0].name","required;不能为空");
 37         Map<String, Object> rstList = bValidt.validByPath(dsList, stdMapA,true);
 38 
 39         String dsStr1 = JackJsonUtils.getStdJsonStr("" +
 40                 "{\n" +
 41                 "    items:[\n" +
 42                 "        {\n" +
 43                 "            no:1,\n" +
 44                 "            name:\"wang\",        \n" +
 45                 "            son:{" +
 46                 "               xx:12"+
 47                 "            }"+
 48                 "        },\n" +
 49                 "        {\n" +
 50                 "            no:'11',\n" +
 51                 "            name:\"wang\",\n" +
 52                 "            son:{" +
 53                 "               xx:55"+
 54                 "            }"+
 55                 "        }\n" +
 56                 "    ]\n" +
 57                 "}" +
 58                 "");
 59         Map<String, Object> dsMap1 = JackJsonUtils.fromJson(dsStr1, Map.class);
 60 
 61         Map<String,String> ruleMap1=new LinkedHashMap<>();
 62         ruleMap1.put("items.[0].no","num;3;不是数或小数位数出错");
 63         ruleMap1.put("items.[0].son.xx","num;3;不是数或小数位数出错");
 64         ruleMap1.put("items.[0].name","required; 不能为空");
 65         Map<String, Object> rst1 = bValidt.validByPath(dsMap1, ruleMap1,true);
 66 
 67         String dsStr2 = JackJsonUtils.getStdJsonStr("" +
 68                 "{\n" +
 69                 "    items:[\n" +
 70                 "        {\n" +
 71                 "            no:1,\n" +
 72                 "            name:\"wang\",        \n" +
 73                 "            son:[{" +
 74                 "               xx:12"+
 75                 "            }," +
 76                 "            {" +
 77                 "               xx:13"+
 78                 "             }] "+
 79                 "        },\n" +
 80                 "        {\n" +
 81                 "            no:'11',\n" +
 82                 "            name:\"wang\",\n" +
 83                 "            son:[{" +
 84                 "               xx:22"+
 85                 "            }," +
 86                 "            {" +
 87                 "               xx:23"+
 88                 "             }] "+
 89                 "        }\n" +
 90                 "    ]\n" +
 91                 "}" +
 92                 "");
 93         Map<String, Object> dsMap2 = JackJsonUtils.fromJson(dsStr2, Map.class);
 94 
 95         Map<String,String> ruleMap2=new LinkedHashMap<>();
 96         ruleMap2.put("items.[0].no","num;3;不是数或小数位数出错");
 97         ruleMap2.put("items.[0].son.[0].xx","num;3;不是数或小数位数出错");
 98         ruleMap2.put("items.[0].name","required; 不能为空");
 99         Map<String, Object> rst2 = bValidt.validByPath(dsMap2, ruleMap2,true);
100 
101         System.out.println();
102     }
103 //    @Test
104     void valid() {
105         //展示通过js对象转标准JSON字符串,再转成Map实例
106         String dsStr = JackJsonUtils.getStdJsonStr("{no:1,name:''}");
107         Map<String, Object> dsMap = JackJsonUtils.fromJson(dsStr, Map.class);
108 
109         String stdStr = JackJsonUtils.getStdJsonStr("{\n" +
110                 "    name:\"required; 不能为空 \",\n" +
111                 "    no: \"num;3;不是数或小数位数出错\"\n" +
112                 "}");
113         Map<String, Object> stdMap = JackJsonUtils.fromJson(stdStr, Map.class);
114 
115 
116         Map<String, Object> rst = bValidt.valid(dsMap, stdMap);
117 
118 
119         String dsStr1 = JackJsonUtils.getStdJsonStr(
120                 "" +
121                         "{\n" +
122                         "    items:[\n" +
123                         "        {\n" +
124                         "            no:1,\n" +
125                         "            name:\"wang\",        \n" +
126                         "        },\n" +
127                         "        {\n" +
128                         "            no:'11',\n" +
129                         "            name:\"wang\",\n" +
130                         "        }\n" +
131                         "    ]\n" +
132                         "}" +
133                         "");
134         Map<String, Object> dsMap1 = JackJsonUtils.fromJson(dsStr1, Map.class);
135 
136         String stdStr1 = JackJsonUtils.getStdJsonStr("" +
137                 "{\n" +
138                 "    items:[\n" +
139                 "        {\n" +
140                 "            name:\"required; 不能为空 \",\n" +
141                 "            no: \"num;2;不是数或小数\"\n" +
142                 "        },\n" +
143                 "        {\n" +
144                 "            name:\"required; 不能为空 \",\n" +
145                 "            no: \"num;不是数或小数\"\n" +
146                 "        }\n" +
147                 "    ]\n" +
148                 "}" +
149                 "");
150         Map<String, Object> stdMap1 = JackJsonUtils.fromJson(stdStr1, Map.class);
151         Map<String, Object> rst1 = bValidt.valid(dsMap1, stdMap1);
152 
153         String dsStr2 = JackJsonUtils.getStdJsonStr(
154                 "" +
155                         "{\n" +
156                         "    no:'11',\n" +
157                         "    name:'name11',\n" +
158                         "    items:[\n" +
159                         "        {\n" +
160                         "            no:1,\n" +
161                         "            name:\"wang\",\n" +
162                         "            son:[\n" +
163                         "                'dd','ee'\n" +
164                         "            ],\n" +
165                         "        },\n" +
166                         "        {\n" +
167                         "            no:11,\n" +
168                         "            name:\"wang\",\n" +
169                         "        }\n" +
170                         "    ]\n" +
171                         "}" +
172                         "");
173         Map<String, Object> dsMap2 = JackJsonUtils.fromJson(dsStr2, Map.class);
174 
175         String stdStr2 = JackJsonUtils.getStdJsonStr("" +
176                 "{\n" +
177                 "    no:'num;3;不是数或小数',\n" +
178                 "    items:[\n" +
179                 "        {\n" +
180                 "            name:\"required; 不能为空 \",\n" +
181                 "            no: \"num;3;不是数或小数\",\n" +
182                 "            son:[\n" +
183                 "                \"num;不是数或小数\"\n" +
184                 "            ]\n" +
185                 "        }\n" +
186                 "    ]\n" +
187                 "}" +
188                 "");
189         Map<String, Object> stdMap2 = JackJsonUtils.fromJson(stdStr2, Map.class);
190         Map<String, Object> rst2 = bValidt.valid(dsMap2, stdMap2);
191 
192 
193         List<Map<String,Object>> dsList=new ArrayList<>() ;
194         Map<String,Object> dsMapA=new LinkedHashMap<>();
195         dsList.add(dsMapA);
196         dsMapA.put("no","11");
197         dsMapA.put("name","name11");
198         dsMapA=new LinkedHashMap<>();
199         dsList.add(dsMapA);
200         dsMapA.put("no","22");
201         dsMapA.put("name","name22");
202 
203         List<Map<String,Object>> stdList=new ArrayList<>() ;
204         Map<String,Object> stdMapA=new LinkedHashMap<>();
205         stdList.add(stdMapA);
206 
207 //        stdMapA.put("no","num;不是数字");
208         stdMapA.put("no","type;String;不是指定类型");
209         stdMapA.put("name","required;不能为空");
210         Map<String, Object> rst3 = bValidt.valid(dsList, stdList);
211 
212 
213         System.out.println();
214 
215     }
216 }
View Code

 

posted @ 2020-05-17 16:01  isV1  阅读(659)  评论(0编辑  收藏  举报