Search code examples
javastringreplaceall

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


I have oldId and newId and I want to replace oldId with newId.

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));
}

With the above code I have, it will print newResponse as -

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

If you see closely, two fields got change, one is user_id and second is matter since replaceAll will replace everything to a new one.

  • user_id 876 got change to 54321
  • matter 55787693 got change to 5575432193

What I am looking for is - It should only replace the full number to a new number instead of modifying any number in the middle to a new number. As an example - user_id 876 is a full number so it should replace 876 only to 54321 notmatter in which 876 is in the middle.

In general, I want to replace a number to a new number completely. I don't want to replace something in the middle of it. Is there any way to do this?


Solution

  • You need to use lookbehind and lookahead to find the non-digit characters, because you don't want to replace them. The syntax that you want, including the lookbehind and lookahead is this.

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

    The syntax for a lookbehind is (?<=X) and for a lookahead is (?=X), where X is an expression matching what you'll find behind or ahead. The way to understand lookbehinds and lookaheads is that they mean "preceded by" and "followed by" respectively.

    So (?<=\D)876(?=\D) means "find something that matches 876, preceded by something that matches \D and followed by something that matches \D. And of course, \D means any character that is not a digit.

    But this expression is not the same as \D876\D, because the lookbehind and lookahead expressions aren't part of what gets replaced by the replaceAll. We don't want the non-digit characters before and after the 876 to get replaced.

    And of course, we escape the backslashes in a String literal by doubling them, so \D is written "\\D".