项目中遇到处理接口返回json的需求:
将json键中的kebab-case转换为camelCase
为解决需求进行了一系列学习,在此记录学习过程。
首先了解几种case:
命名法
- camelCase 驼峰命名(lowerCamelCase)
- snake_case 蛇形命名
- kebab-case 短横线命名
- PascalCase 帕斯卡命名(UpperCamelCase)
正则表达式
匹配json中的key
由于觉得以JSONObject形式添一个键值对再删一个键值对的操作,不是很合理,相当于所有键为一个单词以上的键值对都重新添加,如果数据量很大…
于是想直接处理字符串,便有了一晚上的琢磨(ŏ_ŏ),总算被我试出来了
先把最终匹配到所有键的正则表达式放在这里( 对于我使用的json数据是完全正确的,如果有遗漏的情况欢迎指点 ):
// by Sheri
// jdk8
String regex = "\"(.+?)\":.*?(?=[,{}])\"?";
// String json = "(a json string)";
Matcher m = Pattern.compile(regex).matcher(json);
// match到所有的键
while(m.find()){
if(m.group(1).contains("-")){
// more than one word
// 进行kebab-case到camelCase的转换
}
}
命名法转换
起初想直接替换,jdk11中已有replaceAll的第二种调用方式,可以使用lamda表达式直接写好转换逻辑作为参数传入:
// jdk11
String s = Pattern.compile("-([a-z])")
.matcher(json)
.replaceAll(matchResult
-> matchResult.group(1)
.toUpperCase());
但是由于项目某处的import,需要使用jdk8环境,没有这一个重载的方法,并且Matcher的操作有种种限制,我可能没有以最简洁的方式解决这个问题,但为了寻找能够正确完成需求的方法,我算是对Matcher进行了一番研究
解决问题流水账:
——试图直接用
m.replaceAll(m.group(1).toUpperCase())
- 存在问题:由于要保证修改的是键不是值,所以第一层的matcher匹配的是完整的键字符串。如果一个键由三个或以上单词组成,即会出现两个或以上的"-"(hyphen),此时matcher的region会是整个key字符串,而上述replaceAll则会同时将所有"-[a-z]“替换成第一个”-[a-z]"的大写。
- 例如:last-return-date 替换成 lastReturnRate,而本该依次m.find()去转换才能避免该问题。
——借助StringBuffer修改非预期的命名法