MyUtils

114 阅读2分钟

ChekUtils

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.Collection;

public class CheckUtils {


    public static Require require() {
        return new Require();
    }


    public static class Require {

        public Require notNull(Object obj, String fieldTip) {
            if (obj == null) {
                throw new ParamCheckException(fieldTip + "不存在");
            }
            return this;
        }

        public Require notEmpty(String value, String fieldTip) {
            if (StringUtils.isEmpty(value)) {
                throw new ParamCheckException(fieldTip + "不能为空");
            }
            return this;
        }

        public Require notBlank(Object obj, String fieldTip) {
            if (obj == null) {
                throw new ParamCheckException(fieldTip + "不能为空");
            }
            return this;
        }

        public Require notEmpty(Collection<?> collection, String fieldTip) {
            if (CollectionUtils.isEmpty(collection)) {
                throw new ParamCheckException(fieldTip + "不能为空");
            }
            return this;
        }

    }
}

JSON2JSON


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * JSON映射为JSON工具
 *
 * @author tcyao2
 */
@Slf4j
public class Json2JsonUtils {

    private final static String ARR_CHARS = "[]";


    /**
     * 判断sourceJson是否符合baseJson的结构,即判断两个JSON的结构是否相同
     * 前提条件是 两个JSON中如果有数组的话,
     * 数组的元素必须是相同的结构,不然会校验不准确。
     *
     * @param sourceJson 待检测的JSON
     * @param baseJson   基础json
     * @return 结构相同返回true
     */
    public static boolean isJsonMatch(JSONObject sourceJson, JSONObject baseJson) {
        if (sourceJson == null) {
            return baseJson == null;
        }
        Map<String, Object> jsonStructurePaths = JsonToJsonUtils.jsonStructurePaths(sourceJson);
        Map<String, Object> baseJsonPaths = JsonToJsonUtils.jsonStructurePaths(baseJson);

        for (Map.Entry<String, Object> baseJsonEntry : baseJsonPaths.entrySet()) {
            String templateKeyPath = baseJsonEntry.getKey();
            Object templateVal = baseJsonEntry.getValue();
            Object jsonVal = jsonStructurePaths.get(templateKeyPath);
            // 如果没有,直接通过
            if (jsonVal == null) {
                continue;
            }
            boolean typeMatch = templateVal.getClass().getSimpleName()
                    .equalsIgnoreCase(jsonVal.getClass().getSimpleName());
            if (!typeMatch) {
                log.warn("JSON校验不通过!JSONPath:{},模板Key类型:{},样本Key类型:{}",
                        templateKeyPath, templateVal.getClass().getSimpleName(),
                        jsonVal.getClass().getSimpleName());
                return false;
            }
        }
        return true;
    }


    /**
     * 返回一个JSON 对应的JSONPath 结构
     *
     * @return map, key:jsonpath
     * 格式: /user/name
     * /user/pets/`*`/name
     * value:对应的值
     */
    private static Map<String, Object> jsonStructurePaths(JSONObject jsonObject) {
        Map<String, Object> jsonPaths = JSONPath.paths(jsonObject);
        HashMap<String, Object> map = new HashMap<>();

        jsonPaths.forEach((k, v) -> {
            if (k.equals("/")) {
                return;
            }
            String keySt = k.replaceAll("/\d+", "/*");
            map.put(keySt, v);
        });
        return map;
    }

    public static JsonMappingCheckResult checkJsonKeyPair(JsonKeyPair keyPair) {
        JsonMappingCheckResult result = new JsonMappingCheckResult();
        result.setIdPair(keyPair.getIdPair());
        String sourcePath = keyPair.getSourceKeyPath();
        String targetPath = keyPair.getTargetKeyPath();
        int arrCountAtTarget = arrLevel(targetPath);
        int arrCountAtSource = arrLevel(sourcePath);
        if (arrCountAtTarget > arrCountAtSource) {
            result.setMappingError(true);
            result.setErrorEnum(JsonMappingErrorEnum.ARRAY_LEVEL_MAPPING_ERROR);
            return result;
        }

        boolean dataTypeCheckPass = checkByDataType(keyPair.getSourceKeyDataType(),
                keyPair.getTargetKeyDataType());
        if (!dataTypeCheckPass) {
            result.setMappingError(true);
            result.setErrorEnum(JsonMappingErrorEnum.KEY_TYPE_MAPPING_ERROR);
        }
        return result;
    }

    private static boolean checkByDataType(JsonKeyDataTypeEnum sourceType, JsonKeyDataTypeEnum targetType) {
        return sourceType.equals(targetType);
    }

    public static List<JsonMappingCheckResult> checkJsonKeyPairs(List<JsonKeyPair> jsonKeyPairList) {
        if (CollectionUtils.isEmpty(jsonKeyPairList)) {
            return Collections.emptyList();
        }
        return jsonKeyPairList.stream().map(JsonToJsonUtils::checkJsonKeyPair).collect(Collectors.toList());
    }


    public static JSONObject json2Json(JSONObject sourceObj, Map<String, String> pathMap) {
        pathMap = formatPaths(pathMap);
        Map<String, String> ruleMap = convertRules(pathMap);
        JSONObject targetObj = new JSONObject();
        Map<String, Object> sourcePaths = JSONPath.paths(sourceObj);

        for (Map.Entry<String, Object> sourcePathEntry : sourcePaths.entrySet()) {
            for (Map.Entry<String, String> ruleEntry : ruleMap.entrySet()) {
                String sourcePath = sourcePathEntry.getKey();
                String sourcePathRule = ruleEntry.getValue();
                String targetPathRule = ruleEntry.getKey();

                if (sourcePath.matches(sourcePathRule)) {
                    String targetPath = sourcePath.replaceAll(sourcePathRule, targetPathRule);
                    //获取转换后的value。此处进行类型转换和值集映射转换
                    Object newValue = sourcePathEntry.getValue();
                    if (JSONPath.contains(targetObj, targetPath) && JSONPath.size(targetObj, targetPath) < 0) {
                        //path下已经存在一个值,则需要将类型转换为jsonArray并添加第二个值
                        Object tmp = JSONPath.eval(targetObj, targetPath);
                        Object[] tArray = {tmp, newValue};
                        JSONPath.set(targetObj, targetPath, tArray);
                    } else if (JSONPath.size(targetObj, targetPath) > 1) {
                        //path下已经存在数组对象,直接追加
                        JSONPath.arrayAdd(targetObj, targetPath, newValue);
                    } else {
                        //path不存在,直接添加对象
                        JSONPath.set(targetObj, targetPath, newValue);
                    }
                }
            }
        }
        return targetObj;
    }

    private static Map<String, String> formatPaths(Map<String, String> map) {
        Map<String, String> formatMap = new HashMap<>();
        map.forEach((targetPath, sourcePath) -> {
            formatMap.put(formatTargetPath(targetPath), sourcePath);
        });
        return formatMap;
    }

    private static String formatTargetPath(String targetPath) {
        int num = 1;
        while (targetPath.contains("[]")) {
            targetPath = targetPath.replaceFirst("\[\]", "[" + num + "]");
            num++;
        }
        return targetPath;
    }

    private static int arrLevel(String path) {
        int count = 0;
        if (StringUtils.isEmpty(path) || path.length() < 2) {
            return 0;
        }
        for (int i = 0; i < path.length() - 1; i++) {
            String twoChars = path.charAt(i) + String.valueOf(path.charAt(i + 1));
            if (twoChars.equals(ARR_CHARS)) {
                count++;
            }
        }
        return count;
    }

    private static Map<String, String> convertRules(Map<String, String> map) {
        Map<String, String> ruleMap = new HashMap<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            //针对目标路径进行转换
            String key = "/" + entry.getKey().replaceAll("\[(\d+)\]", "/\$$1").replace(".", "/");
            //针对源路径进行转换
            String value = "/" + entry.getValue().replaceAll("\[\]", "/(\\d+)").replace(".", "/");
            ruleMap.put(key, value);
        }
        return ruleMap;
    }


}