需求说明

最近在公司项目中遇到一个需要,需要在用户输入的入参数据中,将数据里面${}占位符的数据替换为真实的数据方式,以下提供两种方式

使用Api
  • JsonUtils:自己封装的工具类,其中对Jackson的api进行封装,可以自行替换
方式一

https://blog.csdn.net/weixin_43915643/article/details/123231563

缺点:
  • 正则表达式匹配,转换后会出现多余的引号,导致替换后的数据在转换为json格式就会出现转换不了的问题
  • 正则表达式过于复杂,后期修改就不好维护
方式二

方式二的好处在于使用了 Map的方式处理了json格式的数据,也不会出现多余的双引号的问题。缺点就是可能会出来无限深度的递归

public static String processMap(Map<String, Object> model, Object data) throws InvocationTargetException,
                                                                                   IllegalAccessException,
                                                                                   NoSuchMethodException {
        //获取到所有map的key value
        Map<String, Object> valueMap = new HashMap<>(model);
        for (Map.Entry<String, Object> next : model.entrySet()) {
            String modelKey = next.getKey();
            //获取到value的数据
            Object modelValue = next.getValue();
            String modelValueStr = JsonUtils.toJson(modelValue);
            boolean isJson = JsonUtils.isJson(modelValueStr);
            //处理占位符,判断是否时标准的json结构
            if (!isJson) {
                //截取出占位符的key
                String process = doProcess(modelValueStr, data);
                valueMap.put(modelKey, process);
            } else {
                Object parse = JsonUtils.parse(modelValueStr, Object.class);
                if (parse instanceof Map) {
                //将数据为Map的进行递归处理
                    String processMap = processMap(JsonUtils.toMap(modelValueStr, String.class, Object.class), data);
                    valueMap.put(modelKey, JsonUtils.toMap(processMap, String.class, Object.class));
                }
            }
        }
        return JsonUtils.toJson(valueMap);
    }

	/**
     * 进行字符串的处理
     */
private static String doProcess(String str, Object data) throws IllegalAccessException,
                                                                         InvocationTargetException,
                                                                         NoSuchMethodException {
        Matcher matcher = PLACEHOLDER_PATTERN.matcher(str);
        StringBuffer values = new StringBuffer();
        while (matcher.find()) {
            String key = matcher.group(1);
            Object value = PropertyUtils.getProperty(data, key);
            Assertions.notNull(value, String.format("占位符未匹配到数据:%s", key));
            //解决:Illegal group reference 对字符串value进行 encode 防止value中有 $ 符号导致的替换异常
            matcher.appendReplacement(values, JsonUtils.toJson(value).replaceAll("\\$", "RDS_CHAR_DOLLAR"));
        }
        matcher.appendTail(values);
        return values.toString();
    }
注意

这里在使用jackson过程中遇到过一个坑,就是使用jackson api,用toJson() 方法转换下面这种格式的数据:

"{\"name\": \"zhangfei\"}___xxxx"

“{“test”:“name”}___xxxxx” 使用Jackson时会将 ___xxxxx字符截取掉(Jackson默认会使用 } 结尾作为结尾的符号,然后丢弃掉后面的数据),就会导致这个字符串也是一个合法的json,包括后续使用parse() 进行转换

解决方案
public static boolean isJson(@NotNull ObjectMapper mapper, String jsonInString) {
       if (StringUtils.isEmpty(jsonInString)) {
           return false;
       }
       try {
       	//jackson在读取到不是标准的json时会抛出错误,则不是json格式
           JsonNode jsonNode = mapper.readTree(jsonInString);
           //在读取json完之后,判断读取完的字符串是否跟原来字符串相同,如果不相同就判断为false
           String jStr = jsonNode.toString();
           // trimAllWhitespace() 去掉所有的空格符号
           return StringUtils.trimAllWhitespace(jStr).equals(StringUtils.trimAllWhitespace(jsonInString));
       } catch (IOException e) {
           return false;
       }
   }


public static String toJson(ObjectMapper mapper, Object object, boolean pretty) {
       if (object == null) {
           return StringPool.EMPTY_JSON;
       }
       // 如果是 string, 先转为 object 再转为 json, 避免转义字符
       if (object instanceof String) {
           String str = StringUtils.trimWhitespace((String) object);
           //在执行toJson的时候会先判断是否是标准的json格式,如果不是就按照字符串的方式返回
           if (isJson(mapper, str)) {
               object = parse(str, Object.class);
           } else {
               // 非 json 字符串, 直接返回原始字符串
               return str;
           }
       }

       try {
           String json;
           if (pretty) {
               json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
           } else {
               json = mapper.writeValueAsString(object);
           }
           return json;
       } catch (JsonProcessingException e) {
           throw Exceptions.unchecked(e);
       }
   }
GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐