How to replace a number completly without modifyin

2019-08-27 04:33发布

问题:

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?

回答1:

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".



回答2:

The correct way would be to process JSON data as a JSON data.

Any string substitution or regex you employ would be fragile and could potentially break your code for some input JSON string. For example, what if, both user_id and matter values come in to be the same. Your assumption of not replacing in the middle simply fails then.

To process the JSON is just three lines of code:

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

I'm assuming you wouldn't require oldId then. In case, your input string could contain multiple user_ids, you would simply extend my example to check and replace the appropriate JSONObject.

Please note that I'm using the org.json.jar for Java from www.json.org. You're free to use any JSON parser you like.


Since, you've re-posted this question but have provided the complete JSON string format there, I've proposed this solution again but with updates that handle all your possible JSON data types for user_id.