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;
}
}