【问题标题】:JSON string manipulation using regular expression使用正则表达式处理 JSON 字符串
【发布时间】:2018-04-19 08:54:01
【问题描述】:

您好,我一直在尝试让正则表达式替换 JSON 字符串键名中的点 (.)。我不想使用 JSONObject 将字符串转换为 JSON。

所以对于像这样的 JSON 字符串:

{
    "data": {
        "property": "0",
        "property_value": "0",
        "property": "0",
        "pro.per.ty": "0",
        "pr.op.er.ty": "0.0",
        "property": "0.0",
        "proper_ty": "0.0",
        "group": "oneGroup",
        "newprop": "0",
        "total": {
            "0": "0",
            "99": "0",
            "100": "0",
            "25": "0",
            "90": "0",
            "50": "0",
            "95": "0",
            "99.5": "0",
            "75": "0"
        },
        "requests": "0"
    }
}

我希望最终的字符串是

{
    "data": {
        "property": "0",
        "property_value": "0",
        "property": "0",
        "pro_per_ty": "0",
        "pr_op_er_ty": "0.0",
        "property": "0.0",
        "proper_ty": "0.0",
        "group": "oneGroup",
        "newprop": "0",
        "total": {
            "0": "0",
            "99": "0",
            "100": "0",
            "25": "0",
            "90": "0",
            "50": "0",
            "95": "0",
            "99_5": "0",
            "75": "0"
        },
        "requests": "0"
    }
}

解决方案需要高性能,时间低于 10 毫秒。

我可以使用表达式 "(\w*\.\w*)+\": 捕获带有 (.) 的键,但我无法正确获取子组以执行替换。

【问题讨论】:

  • 所以您不只是想用下划线替换 all 点的实例,而只想替换键中的点?
  • 我不想使用 JSONObject 将字符串转换为 JSON。 为什么?

标签: java json regex


【解决方案1】:

我能够提出以下建议,但不确定是否可以通过减少创建的 String 对象的数量来改善这一点

String cleanse(final String jsonString){
Pattern pattern = Pattern.compile("((?:\\w*\\.\\w*)+)\"\\s*?:");
String str = jsonString;
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
str = str.replace(matcher.group(1),matcher.group(1).replaceAll("\\.","_"));
}
return str;
}

【讨论】:

    【解决方案2】:

    您也可以考虑以下基于非正则表达式的方法:

    public static String cleanse( String str )
    {
        String updated = Arrays.stream( str.split( "," ) ).map( value -> {
            if ( !value.contains( ":" ) )
            {
                return value;
            }
            String[] pair = value.split( ":" );
            StringBuilder sb = new StringBuilder();
            int i = 0;
            while ( i < pair.length - 1 )
            {
                sb.append( pair[i] ).append( ":" );
                i++;
            }
            return sb.toString().replace( '.', '_' ) + pair[i];
        } ).collect( Collectors.joining( "," ) );
    
        return updated;
    }
    

    因为它没有使用模式匹配,所以它应该是高性能的。

    【讨论】:

    • 感谢@Mahendra 的解决方案。在实际数据字符串 (~1.8kb) 上尝试会产生 50+ 毫秒的平均时间。模式匹配始终产生约 5 毫秒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    相关资源
    最近更新 更多