如何在中间不修改的情况下完全替换数字?

How to replace a number completly without modifying in the middle?

我有 oldIdnewId,我想用 newId 替换 oldId

public static void main(String[] args) {
    String jsonString = "{\"user_id\":{\"long\":876},\"client_id\":{\"int\":0},\"affinity\":[{\"try\":{\"long\":55787693},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}";

    // some other json strings -

    // String jsonString = "{\"user_id\":{\"string\": \"876\"},\"client_id\":{\"int\":0},\"affinity\":[{\"try\":{\"long\":55787693},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}";
    // String jsonString = "{\"user_id\": \"876\", \"client_id\":{\"int\":0},\"affinity\":[{\"try\":{\"long\":55787693},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}";
    // String jsonString = "{\"user_id\": 876, \"client_id\":{\"int\":0},\"affinity\":[{\"try\":{\"long\":55787693},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}";
    // String jsonString = "{\"user_id\": null, \"client_id\":{\"int\":0},\"affinity\":[{\"try\":{\"long\":55787693},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}";

    String newResponse = changeJsonString(jsonString, "876", "54321");
    System.out.println(newResponse);
}

private static String changeJsonString(String originalResponse, String oldId, String newId) {     
    return originalResponse.replaceAll(String.valueOf(oldId), String.valueOf(newId));
}

使用上面的代码,它将 newResponse 打印为 -

{\"user_id\":{\"long\":54321},\"client_id\":{\"int\":0},\"affinity\":[{\"matter\":{\"long\":5575432193},\"scoring\":{\"float\":0.19}},{\"try\":{\"long\":1763},\"scoring\":{\"float\":0.0114}}]}    

如果你仔细观察,有两个字段发生了变化,一个是 user_id,第二个是 matter,因为 replaceAll 会将所有内容替换为新的。

我正在寻找的是 - 它应该只将完整数字替换为新数字,而不是将中间的任何数字修改为新数字。例如 - user_id 876 是一个完整数字,因此它应该仅将 876 替换为 54321 而不是 matter,其中 876 位于中间。

一般来说,我想把一个号码完全替换成一个新号码。我不想更换中间的东西。有什么办法吗?

您需要使用lookbehind 和lookahead 来查找非数字字符,因为您不想替换它们。你想要的语法,包括lookbehind和lookahead就是这个。

originalResponse.replaceAll("(?<=\D)" + oldId + "(?=\D)", String.valueOf(newId));

lookbehind 的语法是 (?<=X),而 lookahead 的语法是 (?=X),其中 X 是一个匹配你将在后面或前面找到的内容的表达式。理解 lookbehinds 和 lookaheads 的方法是它们分别表示 "preceded by" 和 "followed by"。

所以 (?<=\D)876(?=\D) 的意思是“找到匹配 876 的东西,前面是匹配 \D 的东西,然后是匹配 \D 的东西。当然,\D 表示任何不是数字的字符。

但是这个表达式与 \D876\D 不同,因为后向和先行表达式不是被 replaceAll 替换的部分。我们不希望替换 876 前后的非数字字符。

当然,我们通过将 String 文字中的反斜杠加倍来转义它们,所以 \D 写成 "\D".

正确的方法是将 JSON 数据作为 JSON 数据处理。

您使用的任何字符串替换或正则表达式都是脆弱的,并且可能会破坏某些输入 JSON 字符串的代码。例如,如果 user_idmatter 值相同会怎样。那么你不在中间替换的假设就失败了。

处理JSON只需三行代码:

private static String changeJsonString(String originalResponse, String newId) {     
    try {
        JSONObject root = new JSONObject(originalResponse);
        ((JSONObject) root.get("user_id")).put("long", Long.parseLong(newId));
        return root.toString();
    } catch (JSONException e) {
        e.printStackTrace();
        return null;
    }
}

我假设您那时不需要 oldId。如果您的输入字符串可能包含多个 user_id,您只需扩展我的示例以检查并替换适当的 JSONObject.

请注意,我使用的是 org.json.jar for Java from www.json.org。您可以随意使用任何您喜欢的 JSON 解析器。


因为,你已经重新发布了这个问题,但在那里提供了完整的 JSON 字符串格式,我提出了这个解决方案 但更新可以处理所有可能的 JSON 数据类型user_id.