11
回答
json字符串中key值驼峰命名与下划线命名互转
华为云数据库免费试用   

最近正在开发一个工具类,目的是把一整个json字符串中的所有key值做驼峰和下划线之间的转换。

目前想到两种方案

1.把所有的key值用正则提取替换。感觉这种方式过于简单粗暴

2.把json字符串解析成json object 然后遍历key,生成目标的key与json串,但是这种方式涉及到key值嵌套递归问题,不好写

请问各位大神有没有更好的解决方案,现在百度谷歌查询的都是针对指定字段的转换,和我想要做的所有key值相差很远。

举报
共有11个答案 最后回答: 2年前
public static void main(String[] args) {
        String str = "{'user_name':'ok','user_sex':0,object_info':{'business_code':'0001','object_info2':{'object_1':'ok'}}}";
        String strs[] = str.split(":");
        /*for (String is : strs) {
            System.out.println(is);
        }*/
        StringBuilder sb = new StringBuilder();
        for (String o : strs) {
            String _tmp[]  = o.split(",");
            if(_tmp.length > 1){
                //替换数组2的值为驼峰
                sb.append(_tmp[0]).append(",").append(underlineToCamel(_tmp[1]));
            }else{
                //替换''里的数值为驼峰
                sb.append(underlineToCamel(_tmp[0]));
            }

            sb.append(":");
        }

        System.out.println(sb.substring(0,sb.length() - 1).toString());
    }


    public static final char UNDERLINE='_';
    public static String camelToUnderline(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if (Character.isUpperCase(c)){
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }
    public static String underlineToCamel(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if (c==UNDERLINE){
                if (++i<len){
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }
    public static String underlineToCamel2(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        StringBuilder sb=new StringBuilder(param);
        Matcher mc= Pattern.compile("_").matcher(param);
        int i=0;
        while (mc.find()){
            int position=mc.end()-(i++);
            //String.valueOf(Character.toUpperCase(sb.charAt(position)));
            sb.replace(position-1,position+1,sb.substring(position,position+1).toUpperCase());
        }
        return sb.toString();
    }



--- 共有 2 条评论 ---
CloudArchitect回复 @CloudArchitect : 这种方案感觉会有问题。 2年前 回复
CloudArchitect感谢回复,这么做是有问题的,比如在值字段里面有“,”。就bug了 测试用例: 输入:String str = "{'user_name':'o,k','user_sex':0,object_info':{'business_code':'0001','object_info2':{'object_1':'ok'}}}"; 2年前 回复
我给你写了一个,用的递归,fastjson库自行下载导入 ,传入的参数即是转换后的结果,支持JSONObject、JSONArray的各种嵌套,应该满足你的需求了
    public final static Object convert(String json) {
        Object obj = JSON.parse(json);
        convert(obj);
        return obj;
    }

    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                            }
                        }
                    }
                    jo.remove(key);
                    jo.put(sb.toString(), value);
                }
                convert(value);
            }
        }
    }

呃,如果用jackson,可以直接在java类的字段上用@JsonProperty声明对应的key.

如果是任意json的话,要考虑到 解析后的json模型应当支持一个任意层次的树。实际上大多数完善的json库都支持能做到这个支持。这样就是要做树的遍历了。

--- 共有 9 条评论 ---
szwx855回复 @BoXuan :嗯,解决了就好。。 2年前 回复
节节草回复 @szwx855 : 抱歉,首先贴在上面的代码我测试了是有问题,已经更正了 2年前 回复
节节草回复 @szwx855 : {"object_info":{"business_code":"0001","object_info2":{"object_1":"ok"}},"user_name":"o,k","user___Sex":0,"json_array":[{"nf":10000,"abc____ddd":"dsjafdsajf"}]} 2年前 回复
节节草回复 @szwx855 : {"userSex":0,"objectInfo":{"businessCode":"0001","objectInfo2":{"object1":"ok"}},"userName":"o,k","jsonArray":[{"nf":10000,"abcDdd":"dsjafdsajf"}]}你试试这个,或者你贴一段给我测试 2年前 回复
节节草回复 @szwx855 : 你可以再测试一下,我测试了是没问题的,注意那个是引用类型的对象,前后都是改变的它 2年前 回复

引用来自“BoXuan”的评论

我给你写了一个,用的递归,fastjson库自行下载导入 ,传入的参数即是转换后的结果,支持JSONObject、JSONArray的各种嵌套,应该满足你的需求了
    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            //此处不能直接遍历keys,不然将报ConcurrentModificationException异常
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                        }
                    }
                    jo.remove(key);
                    jo.put(sb.toString(), value);
                }
                convert(value);
            }
        }
    }

    public final static Object convert(String json) {
        Object obj = JSON.parse(json);
        convert(obj);
        return obj;
    }




改成这样就对了。

public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            String[] array = new String[keys.size()];
            int n = 0;
            for(String key : keys) {
                array[n] = key;
                n++;
            }
            for (String key : array) {
                Object value = jo.get(key);
                jo.remove(key);
                convert(value);
                jo.put(underlineToCamel(key), value);
            }
        }
    }



--- 共有 2 条评论 ---
节节草你这个underlineToCamel算法有问题,你试试中间多个下划线?会有下划线消除不掉的问题,我刚测试了下“abc____abc”这个字符串。 2年前 回复
节节草我写的那个应该没错吧 2年前 回复
关于json的嵌套问题,可以用fastjson 和bean来解决,json的嵌套换成bean之间的嵌套,再使用fastjson的JSONObject.parseObject(resultString, xxxModel.class);自动转成你封装的对象
--- 共有 1 条评论 ---
节节草楼主是要把json中的所有带有下划线的key换成符合驼峰命名规范的key,不是什么json和bean嵌套的问题 2年前 回复
很多json库都有自定义属性名注解配置的,比如fastjson有JSONField的注解,只需要把注解写到model的属性上就可以了

引用来自“dwangel”的评论

呃,如果用jackson,可以直接在java类的字段上用@JsonProperty声明对应的key.

如果是任意json的话,要考虑到 解析后的json模型应当支持一个任意层次的树。实际上大多数完善的json库都支持能做到这个支持。这样就是要做树的遍历了。

你运行下如下代码看下结果。

public class CameTools {

    public static void main(String[] args) {
        String str = "{'user_name':'o,k','user_sex':0,'object_info':{'business_code':'0001','object_info2':{'object_1':'ok'}}}";
        String str2 = "{'object_info':{'business_code':'ok'}}";
        System.out.println(convert(str));
    }

    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            //此处不能直接遍历keys,不然将报ConcurrentModificationException异常
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                            }
                        }
                        jo.remove(key);
                        jo.put(sb.toString(), value);
                    }
                    convert(value);
                }
            }
        }

    }

    public final static Object convert(String json) {
        Object obj = JSONObject.fromObject(json);
        convert(obj);
        return obj;
    }

}



--- 共有 1 条评论 ---
节节草我这边测试这个结果是没问题的 2年前 回复

引用来自“dwangel”的评论

呃,如果用jackson,可以直接在java类的字段上用@JsonProperty声明对应的key.

如果是任意json的话,要考虑到 解析后的json模型应当支持一个任意层次的树。实际上大多数完善的json库都支持能做到这个支持。这样就是要做树的遍历了。

引用来自“szwx855”的评论

你运行下如下代码看下结果。

public class CameTools {

    public static void main(String[] args) {
        String str = "{'user_name':'o,k','user_sex':0,'object_info':{'business_code':'0001','object_info2':{'object_1':'ok'}}}";
        String str2 = "{'object_info':{'business_code':'ok'}}";
        System.out.println(convert(str));
    }

    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            //此处不能直接遍历keys,不然将报ConcurrentModificationException异常
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                            }
                        }
                        jo.remove(key);
                        jo.put(sb.toString(), value);
                    }
                    convert(value);
                }
            }
        }

    }

    public final static Object convert(String json) {
        Object obj = JSONObject.fromObject(json);
        convert(obj);
        return obj;
    }

}



这个没问题

public class CameTools {
    public static void main(String[] args) {
        String str = "{'user_name':'o,k','user_sex':0,'object_info':{'business_code':'0001','object_info2':{'object_1':'ok'}}}";
        String str2 = "{'object_info':{'business_code':'ok'}}";
        System.out.println(convert(str2));
    }
 
    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                            }
                        }
                    }
                    jo.remove(key);
                    jo.put(sb.toString(), value);
                }
                convert(value);
            }
        }
    }
 
    public final static Object convert(String json) {
        Object obj = JSON.parse(json);
        convert(obj);
        return obj;
    }
 
}



顶部